/************************************************************************************************
 *   深圳市摩西尔电子有限公司 @版本所有@
 *
 *   此文件用于箱体链接页面逻辑
 *
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.01.06
 *      内容 : 所有代码
 *************************************************************************************************/

/* exported mc_layout_get_recvcard_data */
/* exported mc_layout_get_module_list */
/* exported mc_layout_get_layout_basic */
/* exported mc_layout_parse_file_set_module */
/* exported mc_layout_construtor_recvcard_xml */
/* exported mc_layout_get_module_size */
/* exported mc_layout_construction_recvcard_xml */
/* exported mc_layout_hub_isOk */
/* exported mc_layout_get_mod_dot_location */
/* exported mc_main_get_module_param_from_sdk */
/* exported mc_main_updata_module_param_from_sdk */
/* exported mc_layout_get_box_basic */
/* exported mc_load_msg_update_data */
/* exported update_box_offset_msg */
/* exported mc_layout_lod_file */
/* exported mc_layout_save_file */
/* exported mc_layout_get_rec_apply_ui */
/* exported mc_layout_apply_data */
/* exported mc_fm_req_param_data */
/* exported mc_save_use_data */
/* exported mc_get_side_box_data */
/* exported mc_screen_layout_json */
/* exported mc_setcard_menu_json */
/* exported mc_setcard_check_port */
/* exported mc_get_line_key */
/* exported mc_reverse_line_arrow_data */
/* exported mc_get_quick_connect_dct_data */
/* exported mc_construct_quick_connect_img */
/* exported mc_screen_send */
/* exported mc_get_screen_size */
/* exported get_concat */
/* exported mc_layout_screen_is_exist */
/* exported get_progress_and_render */
/* exported get_item_grp_data */
/* exported get_div_data */
/* exported construct_straight_line */
/* exported mc_construct_line */
/* exported get_bgc_css */
/* exported create_grp_color */
/* exported move_mod_multi */
/* exported get_mod_merge_data */
/* exported mc_layout_get_boxs_size */
/* exported mc_get_reset_manual_connection */
/* exported mc_judge_add_moudle */
/* exported mc_construct_canvas_msg_html */
/* exported mc_layout_construct_mod */
/* exported mc_layout_construct_box */
/* exported mc_get_select_menu */
/* exported mc_layout_info_disp */
/* exported mc_quick_connect_split */
/* exported mc_get_split_construct */
/* exported mc_get_split_switch_construct */
/* exported mc_screen_add_split_html */
/* exported mc_close_menu */
/* exported get_cur_zomm */
/* exported create_bgm_url */
/* exported set_easy_mode */
/* exported back_to_narmal_mode */
/* exported mc_set_svg_layer_line_size */
/* exported mc_easy_mode_update_pos */
/* exported mc_select_stackitem */
/* exported menu_move */
/* exported mc_setcard_display_hub */
/* exported mc_compare_update_module_msg_txt */
/* exported mc_layout_event */
/* exported mc_save_unset_data */
/* exported mc_get_unset_data */
/* exported mc_get_box_config_data */
/* exported mc_get_module_min_size */
/* exported mc_layout_cache_box */
/* exported mc_construct_transform_apply_param */
/* exported mc_get_create_module_msg */
/* exported mc_get_replace_module_msg */
/* exported mc_layout_operate */
/* exported mc_lang_redo_module */
/* exported mc_lang_undo_module */
/* exported mc_get_format_module_data */
/* exported mc_send_box_base */
/* exported mc_data_transform_sendport */
/* exported mc_card_data_judge */
/* exported mc_handle_param */
/* exported mc_get_adapt_canvasbg_size */
/* exported mc_display_line_when_move */
/* exported mc_select_end_show_menu */
/* exported mc_mouse_pot */
/* exported mc_set_mouse_pot */
/* exported update_select_module_msg */

/* global obj_page_mouse_pot */
/* global mc_select_ranks */
/* global get_box_scale_multiple */
/* global mc_lang_deselect_mod */
/* global mc_get_mouse_pot_module */
/* global mc_select_specify_stack */
/* global add_mod_one */
/* global change_block_bgc */
/* global mc_sdk_apply_box */
/* global obj_same_hub_queue */
/* global obj_same_hub_queue_id */
/* global format_mod_data */
/* global mc_main_load_msg */
/* global mc_main_construct_ui_box */
/* global pako */
/* global mc_sdk_sendcard */
/* global mc_get_top_data */
/* global mc_ui_box */
/* global mc_sdk_param */
/* global mc_sdk_req_mgr */
/* global mc_get_top_fun */
/* global g_obj_lang */
/* global mc_basis_output_get_img */
/* global mc_fm_img_rece */
/* global mc_set_box_offset */
/* global mc_card_pos */
/* global mc_sdk_module */
/* global ARY_USE_MOD_NAME */
/* global get_progress_color */
/* global get_progress_bar_html */
/* global mc_get_data_param */
/* global mc_analysis_transform_msg */
/* global mc_get_optsize_msg */
/* global $ */
/* global mc_get_module_msg */
/* global mc_crypto_set_box_md5_to_key */
/* global g_ary_info_disp */
/* global delete_mod_queue */
/* global set_mod_bgimg */
/* global ui_easy_mode_size */
/* global mc_util_round */
/* global b_add_screen */
/* global str_mod_init_val */
/* global mc_util_is_object */
/* global mc_lang_transformation_module */
/* global mc_lang_positioning_module */
/* global mc_lang_lock_mod */
/* global mc_lang_ligature_module */
/* global mc_lang_edit_mod */
/* global mc_selectd_link_data_merge */
/* global mc_add_css_rules */
/* global mc_get_appoint_obj */
/* global mc_get_child_pot_size */
/* global str_recvcard_class_name_prefix */
/* global update_opt_easy_mode */
/* global update_connect_queue */
/* global clear_box_canvas */
/* global operate_update_select */
/* global mc_main_get_idx_by_name */
/* global mc_sort_param_value */
/* global md5 */
/* global mc_mod_uncheck */
/* global mc_select_module */
/* global mc_clear_zindex */
/* global mc_select_item_add_zindex */
/* global add_mod_html */
/* global mc_judge_create_canvasbg */
/* global mc_adapt_canvasbg_size */
/* global mc_compose_split_apply */
/* global mc_compose_edit */
/* global mc_filter_tool */
/* global g_obj_save_log */

// **************************************** 新添加 **************************************** //
/* exported create_side_ruler */
/* exported mc_scroll_operation */
/* exported mc_update_ruler_size */
/* exported click_ruler */
/* exported set_select_mod_ruler */
/* exported mc_ruler_mousedown */
/* exported mc_box_coordinate_ruler */
/* exported mc_mousedown_ruler_operation */
/* exported save_transform_data */
/* exported mc_selectd_link_data_port */
/* exported mc_update_setcard_menu_json */
/* exported mc_get_line_key_val */
/* exported init_page_popup_link */
/* exported get_max_min_box_size */
/* exported connect_line_mod */
/* exported connect_group */
/* exported mc_update_line_when_move */
/* exported mc_save_boxsel_data */
/* exported mc_layout_save_set_recvcard_list */
/* exported mc_handle_compose_msg */
/* exported mc_filter_compose_module */
/* exported mc_judge_b_setcard */
/* exported mc_get_edit_border_html */
/* exported mc_card_data_judge */
/* exported mc_edit_display */
/* exported mc_get_edit_border_msg */
/* exported mc_save_compose_edit_operate */
/* exported mc_save_bitmap */
/* exported mc_hl_send_hub_preset */

/* global select_all_operation */
/* global mc_lang_delete_module */
/* global mc_mod_check */
/* global update_selected_mod */
/* global obj_item_checkbox_easy_mode */
/* global mc_util_is_array */
/* global ui_canvasbg_size_w */
/* global ui_canvasbg_size_h */
/* global obj_box_coordinate_ruler */
/* global obj_mousedown */
/* global arr_mod_selected */
/* global mc_rotate_scale_apply */
/* global mc_update_module_msg */
/* global g_obj_side_show_name */
/* global construct_page_popup_link_data */
/* global update_canvas_w */
/* global update_canvas_h */
/* global obj_svg_line_wrap */
/* global mc_util_is_object_dom */
/* global mc_format_style */
/* global mc_get_compose_html */
/* global mc_delete_compose_msg */
/* global mc_transform_operate_apply */
/* global mc_menu_custom_package */
/* global ui_box_scale_step */
/* global mc_scale_set */
/* global obj_compose */
/* global mc_manual_connect_operate_update_param */
/* global mc_bitmap */


var g_obj_box_data_xml_list = {};
var g_arr_color = create_grp_color();
// 卡列表
var str_sendcard_first_name = "";
var str_hubcard_first_name = "";
// 获取卡列表是否成功 true成功
var b_sendcard_getname_success = true; // eslint-disable-line
var b_hubcard_getname_success = true;

// 事件记录对象
var g_obj_event_log = new mc_layout_event();
// 获取箱体参数列表
var g_ary_box_xml_list = [];

// 箭头节点
// var obj_marker_node = mc_construct_marker("init_def", "green");


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取对应名称下标
 * 参数:
 *    @param {Promise<Array>} ary_data 数据数组
 *    @param {Promise<string>} str_name 名称
 * 返回：
 *    @returns {Promise<number>} 对应名称在数组中下标
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.4.9
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_get_data_idx_in_name(ary_data, str_name) {
    if (!Array.isArray(ary_data) || 0 >= ary_data.length) {
        return false;
    }
    for (var idx = 0; idx < ary_data.length; idx++) {
        if (str_name === ary_data[idx].name) {
            return idx;
        }
    }
    return false;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    字符串截取
 * 参数:
 *    @param {Promise<string>} str_param 处理参数
 *    @param {Promise<string>} str_way 处理方式
 * 返回：
 *    @return {Promise<Array>} 截取后生成的数组;
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.4.4
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_main_splice_str(str_param, str_way) {
    if ("string" !== typeof str_param || 0 >= str_param.length) {
        return [];
    }
    if (-1 === str_param.indexOf(str_way)) {
        return [str_param];
    }
    return str_param.split(str_way);
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取箱体链接信息
 * 参数:
 *    @param {Promise<Array>} ary_box_data 储存箱体的数组
 *    @param {Promise<string>} box_name 箱体名称
 * 返回：
 *    @returns {Promise<Array>} 箱体链接数据
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.3.13
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_get_recvcard_data(ary_box_data, box_name) {
    if (!(Array.isArray(ary_box_data)) || 0 >= ary_box_data.length) {
        return false;
    }
    if ("string" !== typeof box_name || 0 >= box_name.length) {
        return false;
    }
    var box_idx = mc_layout_get_data_idx_in_name(ary_box_data, box_name);
    var obj_sdk_recvcard = ary_box_data[box_idx].data.mc_util_get_ui_box_msg();


    var ary_modlist = obj_sdk_recvcard.data;

    return ary_modlist;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取模组列表数组
 * 参数:
 *    @param {Promise<Array>} ary_mod_data 模组列表数组
 * 返回：
 *    @returns {Promise<Array>} 模组列表数组
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.01.06
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_get_module_list(ary_mod_data) {
    if (!(Array.isArray(ary_mod_data)) || 0 >= ary_mod_data.length) {
        return [];
    }
    var ary_module_list = [];

    for (var idx_moduel = 0; idx_moduel < ary_mod_data.length; idx_moduel++) {
        var str_module_name = ary_mod_data[idx_moduel].name;

        ary_module_list.push(str_module_name);
    }
    return ary_module_list;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取箱体页面基本信息
 * 参数:
 *    @param {Promise<Array>} str_get_name 获取尺寸名称
 *    @param {Promise<Boolean>} b_select_type 获取类型 true/false (箱体/模组)
 *    @param {Promise<Uint>} ary_box_data 箱体数据数组
 *    @param {Promise<Uint>} ary_mod_data 模组数据数组
 * 备注:
 * 当有箱体名称时另外两个数组必须传入
 * 返回：
 *     @returns {Promise<object>} 页面基本信息对象
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.01.06
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_get_layout_basic(str_get_name, b_select_type, ary_box_data, ary_mod_data) {
    if ("string" !== typeof str_get_name || 0 >= str_get_name.length) {
        return "";
    }
    var ary_size = [];

    if (b_select_type) {
        // 获取箱体下第一个模组宽高
        var ui_box_idx = mc_layout_get_data_idx_in_name(ary_box_data, str_get_name);
        var str_first_mod_name = ary_box_data[ui_box_idx].data.mc_util_get_box_first_mod_name();
        var obj_first_mod_size = mc_layout_get_module_size(str_first_mod_name, ary_mod_data);

        ary_size = [obj_first_mod_size.width, obj_first_mod_size.height];
    } else {
        ary_size = mc_layout_get_mod_size(str_get_name, ary_mod_data);
    }
    // 获取箱体大小
    var ui_width = ary_size[0];
    var ui_height = ary_size[1];
    // 创建返回数据
    var obj_sdk_param = new mc_sdk_param();


    obj_sdk_param.set_param_clear();
    var str_param_name = "MC_LANG_LABLE_WEITH";
    var str_param_value = ui_width + "";

    obj_sdk_param.set_param_value(str_param_name, str_param_value);
    obj_sdk_param.set_attr_val(str_param_name, "UI_TYPE", "STEP_EDIT");
    obj_sdk_param.set_attr_val(str_param_name, "VAL_TYPE", "uint");
    obj_sdk_param.set_attr_val(str_param_name, "MIN_VAL", "0");
    obj_sdk_param.set_attr_val(str_param_name, "STEP", str_param_value);

    str_param_name = "MC_LANG_LABLE_HEIGHT";
    str_param_value = ui_height + "";
    obj_sdk_param.set_param_value(str_param_name, str_param_value);
    obj_sdk_param.set_attr_val(str_param_name, "UI_TYPE", "STEP_EDIT");
    obj_sdk_param.set_attr_val(str_param_name, "VAL_TYPE", "uint");
    obj_sdk_param.set_attr_val(str_param_name, "MIN_VAL", "0");
    obj_sdk_param.set_attr_val(str_param_name, "STEP", str_param_value);

    str_param_name = "MC_LANG_CASCADE_SYSTEM";
    str_param_value = "0";
    obj_sdk_param.set_param_value(str_param_name, str_param_value);
    obj_sdk_param.set_attr_val(str_param_name, "UI_TYPE", "OPTION");
    obj_sdk_param.set_attr_val(str_param_name, "ARRAY", "0=MC_LANG_OPTION_LEFT_TO_RIGHT,1=MC_LANG_OPTION_RIGHT_TO_LEFT,2=MC_LANG_OPTION_TOP_TO_BOTTOM,3=MC_LANG_OPTION_BOTTOM_TO_TOP");

    str_param_name = "MC_LANG_OUTPUT_MODE";
    str_param_value = "1";
    obj_sdk_param.set_param_value(str_param_name, str_param_value);
    obj_sdk_param.set_attr_val(str_param_name, "UI_TYPE", "OPTION");
    obj_sdk_param.set_attr_val(str_param_name, "ARRAY", "0=MC_LANG_OPTION_NOT_SPLIT,1=MC_LANG_OPTION_TWO_SPLIT,2=MC_LANG_OPTION_THREE_SPLIT,3=MC_LANG_OPTION_FOUR_SPLIT");

    str_param_name = "MC_LANG_PLUG_THE_ORDER";
    str_param_value = "0";
    obj_sdk_param.set_param_value(str_param_name, str_param_value);
    obj_sdk_param.set_attr_val(str_param_name, "UI_TYPE", "OPTION");
    obj_sdk_param.set_attr_val(str_param_name, "ARRAY", "0=MC_LANG_OPTION_POSITIVE_SEQUENCE,1=MC_LANG_OPTION_INVERTED_ORDER");

    return JSON.parse(obj_sdk_param.get_json());
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    解析本地文件,将模组信息添加入自身文件
 * 参数:
 *    @param {Promise<string>} str_xml uibox识别的xml字串
 *    @param {Promise<Array>} ary_mod_data 储存所有模组数据数组
 * 返回：
 *     @returns {Promise<boolean>} 存入结果
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.01.06
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_parse_file_set_module(str_xml, ary_mod_data) {
    if ("string" !== typeof str_xml || 0 >= str_xml.length) {
        return false;
    }
    if (!Array.isArray(ary_mod_data)) {
        return false;
    }
    var obj_ui_box_res = new mc_ui_box();
    var ui_error_code = obj_ui_box_res.mc_util_set_box_xml(str_xml);

    if ("number" === typeof ui_error_code) {
        return false;
    }
    var ui_module_cnt = obj_ui_box_res.mc_util_get_mod_cnt();

    for (var idx_module = 0; idx_module < ui_module_cnt; idx_module++) {
        var str_module_name = obj_ui_box_res.mc_util_get_mod_name_by_idx(idx_module);
        var obj_module_data = obj_ui_box_res.mc_util_get_mod_data_by_name(str_module_name).module_value;
        var ui_mod_idx_max = -1;
        var b_mod_is_exit = false;

        for (var idx_mod = 0; idx_mod < ary_mod_data.length; idx_mod++) {
            var obj_mod_data_loc = ary_mod_data[idx_mod];
            var ui_mod_idx = obj_mod_data_loc.name.match(/\d+/g)[0];

            if (ui_mod_idx > ui_mod_idx_max) {
                ui_mod_idx_max++;
            }
            if (obj_mod_data_loc.data.mc_util_mod_check_equal(obj_module_data.mc_util_mod_get_xml())) {
                b_mod_is_exit = true;
            }
        }
        if (b_mod_is_exit) {
            break;
        }
        ary_mod_data.push({
            name: "MC_MOD_" + (ui_mod_idx_max + 1),
            data: obj_module_data,
            ctrlchip_name: "FPGA",
            hub_name: "FPGA"
        });
    }

    return true;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取模组宽高
 * 参数:
 *    @param {Promise<string>} str_module_name 模组名称
 *    @param {Promise<Array>} ary_mod_data 储存所有模组数据数组
 * 返回：
 *    @returns {Promise<object>} { width: 模组宽度,height: 模组高度}
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.01.06
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_get_module_size(str_module_name, ary_mod_data) {
    if ("string" !== typeof str_module_name || 0 >= str_module_name.length) {
        return false;
    }
    if (!(Array.isArray(ary_mod_data)) || 0 >= ary_mod_data.length) {
        return false;
    }
    var obj_sdk_module = {};

    for (var idx_mod = 0; idx_mod < ary_mod_data.length; idx_mod++) {
        if (str_module_name === ary_mod_data[idx_mod].name) {
            obj_sdk_module = ary_mod_data[idx_mod].data;
            break;
        }
    }

    if (!Object.prototype.hasOwnProperty.call(obj_sdk_module, "mc_util_mod_get_img_rect")) {
        return {};
    }

    var obj_rect = obj_sdk_module.mc_util_mod_get_img_rect(0, 0xffffffff);
    var ui_width = (obj_rect.u32_right + 1 - obj_rect.u32_left);
    var ui_height = (obj_rect.u32_bottom + 1 - obj_rect.u32_top);
    var obj_req = {
        width: ui_width,
        height: ui_height
    };

    return obj_req;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    存入箱体链接信息
 * 参数:
 *    @param {Promise<String>} str_is_upadata 是否为修改箱体数据
 *    @param {Promise<String>} str_updata_box_name 修改箱体名称
 *    @param {Promise<Object>} obj_box_data 箱体链接数据{ctrlchip_name:<string>,hub_name<string>:,data<array>:,edit_val:<array>}
 *    @param {Promise<Array>} ary_box_data 储存箱体的数组
 *    @param {Promise<Functio>} fn_callback 储存模组的数组
 * 返回：
 *    @returns {Promise<Boolean>} 存入结果
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.01.06
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_construction_recvcard_xml(str_is_upadata, str_updata_box_name, obj_box_data, ary_box_data, fn_callback) {
    if (!Array.isArray(ary_box_data)) {
        return false;
    }

    var ui_box_len_max = -1;

    for (var idx_name = 0; idx_name < ary_box_data.length; idx_name++) {
        var str_box_name = ary_box_data[idx_name].name;
        var ui_box_len = Number(str_box_name.match(/\d+/g)[0]);

        if (ui_box_len > ui_box_len_max) {
            ui_box_len_max = ui_box_len;
        }
    }
    var obj_data = {};

    if ("true" === str_is_upadata) {
        var ui_box_idx = mc_layout_get_data_idx_in_name(ary_box_data, str_updata_box_name);

        if ("number" !== typeof ui_box_idx || isNaN(ui_box_idx)) {
            fn_callback(false);
            return false;
        }
        obj_data = ary_box_data[ui_box_idx];
        obj_data.data.mc_util_set_ui_box_msg(obj_box_data);
        // obj_data.ctrlchip_hub_msg = obj_box_data.ctrlchip_hub_msg;
    } else {
        var obj_ui_box = parent.mc_data_box();

        obj_ui_box.mc_util_set_ui_box_msg(obj_box_data);
        obj_data = {
            name: "MC_BOX_" + (ui_box_len_max + 1),
            data: obj_ui_box
            // ctrlchip_hub_msg: obj_box_data.ctrlchip_hub_msg
        };
        ary_box_data.push(obj_data);
    }
    return obj_data.name;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取已知模组走点位置
 * 参数:
 *     @param {Promise<string>} str_module_name 模组名称
 *     @param {Promise<Array>} ary_sdk_moduel 储存所有模组的数组
 * 返回：
 *    @returns {Promise<boolean>} 返回二维数组
 * 修改:
 *   1. 类型 : 创建
 *
 *      作者 : 徐烁超
 *      时间 : 2020.3.13
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_get_mod_dot_location(str_module_name, ary_sdk_moduel) {
    if ("string" !== typeof str_module_name || 0 >= str_module_name.length) {
        return false;
    }
    if (!(Array.isArray(ary_sdk_moduel)) || 0 >= ary_sdk_moduel.length) {
        return false;
    }
    var obj_sdk_module = {};

    for (var idx = 0; idx < ary_sdk_moduel.length; idx++) {
        if (str_module_name === ary_sdk_moduel[idx].name) {
            obj_sdk_module = ary_sdk_moduel[idx].data;
            break;
        }
    }

    var ary_req = [];
    var obj_req = {};
    var ui_str_cnt = obj_sdk_module.mc_util_mod_get_str_cnt();
    var ui_scan_len = obj_sdk_module.mc_util_mod_get_max_scan_len();

    for (var idx_cnt = 0; idx_cnt < ui_str_cnt; idx_cnt++) {
        var ui_scan_cnt = obj_sdk_module.mc_util_mod_get_scan_cnt(idx_cnt);

        for (var idx_scan = 0; idx_scan < ui_scan_cnt; idx_scan++) {
            for (var idx_len = 0; idx_len < ui_scan_len; idx_len++) {
                var obj_data = obj_sdk_module.mc_util_mod_get_pix_info(idx_cnt, idx_scan, idx_len);
                var clr = obj_data.c_color;
                var str_location = obj_data.u32_img_x + "," + obj_data.u32_img_y;

                if ("V" === clr || obj_req[str_location]) {
                    continue;
                }
                obj_req[str_location] = 1;
                ary_req.push([obj_data.u32_img_x, obj_data.u32_img_y]);
            }
        }
    }
    return ary_req;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取芯片信息
 * 参数:
 *    @param {Promise<function>} fun_callback 传入回调函数,不能为空(箱体信息ui_json对象)
 * 返回：
 *    NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.4.4
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_main_get_module_param_from_sdk(fun_callback) {
    if ("function" !== typeof fun_callback) {
        return;
    }
    var obj_sdk_param = new mc_sdk_param();

    obj_sdk_param.set_param_clear();
    mc_main_get_ctrlchip_list_by_sdk(function (ary_ctrlchip) {
        var str_ctrlchip_name = ary_ctrlchip[0];
        var str_ctrlchip_options = "";

        for (var idx = 0; idx < ary_ctrlchip.length; idx++) {
            str_ctrlchip_options += ary_ctrlchip[idx] + ",";
        }
        str_ctrlchip_options = str_ctrlchip_options.substring(0, str_ctrlchip_options.length - 1);
        obj_sdk_param.set_param_value("MC_LANG_CTRLCHIP_LIST", str_ctrlchip_name);
        obj_sdk_param.set_attr_val("MC_LANG_CTRLCHIP_LIST", "UI_TYPE", "OPTION");
        obj_sdk_param.set_attr_val("MC_LANG_CTRLCHIP_LIST", "ARRAY", str_ctrlchip_options);
        obj_sdk_param.set_param_value("MC_LANG_LABLE_HUB", str_ctrlchip_name);
        obj_sdk_param.set_attr_val("MC_LANG_LABLE_HUB", "UI_TYPE", "OPTION");
        obj_sdk_param.set_attr_val("MC_LANG_LABLE_HUB", "ARRAY", str_ctrlchip_name);
        fun_callback(JSON.parse(obj_sdk_param.get_json()));
        return;
    });
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取控制芯片列表
 * 参数:
 *    @param {Promise<function>} fun_callback 传入回调函数,不能为空(控制芯片列表数组)
 * 返回：
 *    NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.4.4
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_main_get_ctrlchip_list_by_sdk(fun_callback) {
    if ("function" !== typeof fun_callback) {
        return;
    }
    var obj_request = new mc_sdk_req_mgr();
    var str_item_json_req = new mc_sdk_param();

    str_item_json_req.set_func("CTRLCHIP_LIST");
    str_item_json_req.set_cmd("GET_PARAM");
    obj_request.push_req(str_item_json_req.get_json(), function (response, status) {
        if ("success" !== status) {
            fun_callback("");
            return;
        }
        var str_item_json_res = new mc_sdk_param();

        str_item_json_res.set_json(response);

        var ui_ctrlchip_param_cnt = str_item_json_res.get_param_cnt();
        var ary_ctrlchip = [];

        for (var idx_chip = 0; idx_chip < ui_ctrlchip_param_cnt; idx_chip++) {
            var str_param_name = str_item_json_res.get_param_name(idx_chip);

            if ("ERROR_CODE" === str_param_name.toUpperCase()) {
                continue;
            }
            var str_chip_name = str_item_json_res.get_param_value(str_param_name);

            if ("string" !== typeof str_chip_name || 0 >= str_chip_name.length) {
                continue;
            }
            ary_ctrlchip.push(str_chip_name);
        }
        fun_callback(ary_ctrlchip);
        return;
    });
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    更新芯片
 * 参数:
 *    @param {Promise<object>} obj_ui_json 箱体信息数据对象,不能为空
 *    @param {Promise<function>} fun_callback 传入回调函数,不能为空(箱体信息数据对象)
 * 返回：
 *    NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2019.11.21
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_main_updata_module_param_from_sdk(obj_ui_json, fun_callback) {
    if ("function" !== typeof fun_callback) {
        return;
    }
    if ("object" !== typeof obj_ui_json) {
        fun_callback();
        return;
    }
    var obj_sdk_param = new mc_sdk_param();

    obj_sdk_param.set_param_clear();
    obj_sdk_param.set_json(JSON.stringify(obj_ui_json));
    var str_ctrlchip_name = obj_sdk_param.get_param_value("MC_LANG_CTRLCHIP_LIST");

    mc_main_get_hub(str_ctrlchip_name, function (str_hub_list) {
        var ary_hub_list = mc_main_splice_str(str_hub_list, ",");
        var str_param_val = obj_sdk_param.get_param_value("MC_LANG_LABLE_HUB");
        // var str_ctrl = obj_sdk_param.get_param_value("MC_LANG_CTRLCHIP_LIST");


        if (-1 === ary_hub_list.indexOf(str_param_val)) {
            str_param_val = ary_hub_list[0];
        }
        // if ("T6" === str_ctrl) {
        //     if (-1 !== ary_hub_list.indexOf("T-75E")) {
        //         str_param_val = "T-75E";
        //     }
        // }
        obj_sdk_param.set_param_value("MC_LANG_LABLE_HUB", str_param_val);
        obj_sdk_param.set_attr_val("MC_LANG_LABLE_HUB", "ARRAY", str_hub_list);
        var obj_ui_json_req = obj_sdk_param.get_json();

        obj_ui_json_req = JSON.parse(obj_ui_json_req);
        fun_callback(obj_ui_json_req);
        return;
    });
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取HUB列表
 * 参数:
 *    @param {Promise<string>} str_ctrlchip_name 控制芯片名称,不能为空
 *    @param {Promise<function>} fun_callback 传入回调函数,不能为空(HUB列表)
 * 返回：
 *    NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2019.12.23
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_main_get_hub(str_ctrlchip_name, fun_callback) {
    if ("string" !== typeof str_ctrlchip_name || 0 >= str_ctrlchip_name.length) {
        fun_callback("");
        return;
    }
    if ("function" !== typeof fun_callback) {
        return;
    }
    var obj_sdk_param_req = new mc_sdk_param();

    obj_sdk_param_req.set_param_clear();
    obj_sdk_param_req.set_cmd("GET_PARAM");
    obj_sdk_param_req.set_func("RECVHUB_LIST");
    obj_sdk_param_req.set_param_value("CTRLCHIP", str_ctrlchip_name);
    $.post("/access_shell", obj_sdk_param_req.get_json(), function (response, status) {
        if ("success" !== status) {
            fun_callback("");
            return;
        }
        obj_sdk_param_req.set_param_clear();
        obj_sdk_param_req.set_json(response);
        var str_hub_list = obj_sdk_param_req.get_param_value(str_ctrlchip_name);

        if ("string" !== typeof str_hub_list || 0 >= str_hub_list.length) {
            fun_callback(str_ctrlchip_name);
            return;
        }
        fun_callback(str_hub_list);
        return;
    });
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取箱体信息
 * 参数:
 *    @param {Promise<string>} box_name 箱体名称
 *    @param {Promise<Array>} ary_box_data 箱体数据
 *    @param {Promise<Array>} ary_mod_data 模组数据
 * 返回：
 *    @returns {Promise<Object>} 箱体基本信息(宽高,主控/hub芯片名)
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.4.9
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_get_box_basic(box_name, ary_box_data, ary_mod_data) {
    if ("string" !== typeof box_name || 0 >= box_name.length) {
        return false;
    }
    if (!Array.isArray(ary_box_data) || 0 >= ary_box_data.length) {
        return false;
    }
    if (!Array.isArray(ary_mod_data) || 0 >= ary_mod_data.length) {
        return false;
    }
    var ui_box_idx = mc_layout_get_data_idx_in_name(ary_box_data, box_name);

    if ("number" !== typeof ui_box_idx) {
        return false;
    }
    var obj_sdk_param = new mc_sdk_param();

    obj_sdk_param.set_param_clear();

    var obj_box_data = ary_box_data[ui_box_idx].data;
    var obj_recvcard_data = obj_box_data.mc_util_get_ui_box_msg();
    var str_ctrlchip_name = obj_recvcard_data.ctrlchip_name;
    var str_hub_name = obj_recvcard_data.hub_name;

    obj_sdk_param.set_param_value("MC_LANG_CTRLCHIP_LIST", str_ctrlchip_name);
    obj_sdk_param.set_attr_val("MC_LANG_CTRLCHIP_LIST", "UI_TYPE", "LABEL");
    obj_sdk_param.set_param_value("MC_LANG_LABLE_HUB", str_hub_name);
    obj_sdk_param.set_attr_val("MC_LANG_LABLE_HUB", "UI_TYPE", "LABEL");
    var ary_box_size = mc_layout_get_box_size(box_name, ary_box_data, ary_mod_data);

    obj_sdk_param.set_param_value("MC_LANG_LABLE_WEITH", ary_box_size[0] + "");
    obj_sdk_param.set_attr_val("MC_LANG_LABLE_WEITH", "UI_TYPE", "LABEL");

    obj_sdk_param.set_param_value("MC_LANG_LABLE_HEIGHT", ary_box_size[1] + "");
    obj_sdk_param.set_attr_val("MC_LANG_LABLE_HEIGHT", "UI_TYPE", "LABEL");
    return JSON.parse(obj_sdk_param.get_json());
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取箱体宽高
 * 参数:
 *     @param {Promise<String>} str_box_name 参数hub值队列
 *     @param {Promise<Array>} ary_box_data 是否为大屏 大屏时额外返回参数三: 箱体个数
 *     @param {Promise<Array>} ary_mod_data 是否为大屏 大屏时额外返回参数三: 箱体个数
 * 返回：
 *     @returns {Promise<Array>}
 *      [ui_m:Number,ui_h:Number];
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.10.27
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_get_box_size(str_box_name, ary_box_data, ary_mod_data) {
    if (
        "string" !== typeof str_box_name || 0 >= str_box_name.length ||
        !Array.isArray(ary_box_data) || 0 >= ary_box_data.length ||
        !Array.isArray(ary_mod_data) || 0 >= ary_mod_data.length
    ) {
        return [0, 0];
    }

    var ui_box_idx = mc_layout_get_data_idx_in_name(ary_box_data, str_box_name);

    if ("number" !== typeof ui_box_idx) {
        return [0, 0];
    }
    var ui_max_x = -1;
    var ui_max_y = -1;
    var ui_min_x = -1;
    var ui_min_y = -1;
    var obj_box_data = ary_box_data[ui_box_idx].data.mc_util_get_ui_box_msg();
    var ary_jx_list = obj_box_data.data;

    for (var idx_jx = 0; idx_jx < ary_jx_list.length; idx_jx++) {
        var ary_mod_list = ary_jx_list[idx_jx].children;

        for (var idx_mod = 0; idx_mod < ary_mod_list.length; idx_mod++) {
            var obj_mod_msg = ary_mod_list[idx_mod];
            var obj_img_offset = {
                rotation: obj_mod_msg.rotation,
                scale: obj_mod_msg.scale,
                offset_x: obj_mod_msg.offset_x,
                offset_y: obj_mod_msg.offset_y,
                width: "",
                height: ""
            };

            var ary_mod_size = mc_layout_get_mod_size(obj_mod_msg.module_name, ary_mod_data);

            obj_img_offset.width = ary_mod_size[0];
            obj_img_offset.height = ary_mod_size[1];

            var obj_mod_offset = mc_get_module_msg(obj_img_offset);
            var ui_mod_max_x = obj_mod_offset.offset_x + obj_mod_offset.width;
            var ui_mod_max_y = obj_mod_offset.offset_y + obj_mod_offset.height;
            var ui_mod_min_x = obj_mod_offset.offset_x;
            var ui_mod_min_y = obj_mod_offset.offset_y;

            if (-1 === ui_max_x) {
                ui_max_x = ui_mod_max_x;
                ui_max_y = ui_mod_max_y;
                ui_min_x = ui_mod_min_x;
                ui_min_y = ui_mod_min_y;
            } else {
                if (ui_mod_max_x > ui_max_x) {
                    ui_max_x = ui_mod_max_x;
                }
                if (ui_mod_max_y > ui_max_y) {
                    ui_max_y = ui_mod_max_y;
                }
                if (ui_min_x > ui_mod_min_x) {
                    ui_min_x = ui_mod_min_x;
                }
                if (ui_min_y > ui_mod_min_y) {
                    ui_min_y = ui_mod_min_y;
                }
            }
        }
    }
    var ui_box_width = ui_max_x - ui_min_x;
    var ui_box_height = ui_max_y - ui_min_y;

    return [ui_box_width, ui_box_height];
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取箱体/大屏宽高
 * 参数:
 *     @param {Promise<Object>} obj_same_hub_queue 参数hub值队列
 *     @param {Promise<Object>} b_screen 是否为大屏 大屏时额外返回参数三: 箱体个数、参数四：使用箱体name
 * 返回：
 *     @returns {Promise<Array>}
 *      false 参数有误
 *      [ui_w,ui_h,ui_cnt];
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.10.21
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_get_boxs_size(obj_same_hub_queue, b_screen) {
    if ("object" !== typeof obj_same_hub_queue) {
        return false;
    }
    var arr_key = Object.keys(obj_same_hub_queue);
    var obj_box_name = {};

    if (0 !== arr_key.length) {
        var ui_min_x = Math.pow(2, 32);
        var ui_min_y = Math.pow(2, 32);
        var ui_max_x = 0;
        var ui_max_y = 0;
        var ui_cnt = 0;
        var ui_grid_w = Number(document.getElementById("mod_box_next").getAttribute("grid_w"));

        for (var idx_key = 0; idx_key < arr_key.length; idx_key++) {
            var arr_line = obj_same_hub_queue[arr_key[idx_key]];

            for (var idx_module = 0; idx_module < arr_line.length; idx_module++) {
                var obj_module = arr_line[idx_module][0];
                var arr_pot = mc_get_optsize_msg(obj_module);
                var arr_size = mc_get_optsize_msg(obj_module, true);
                var u_min_x = arr_pot[0];
                var u_min_y = arr_pot[1];
                var u_max_x = u_min_x + arr_size[0];
                var u_max_y = u_min_y + arr_size[1];

                if (obj_box_name[obj_module.getAttribute("mod_id")]) {
                    obj_box_name[obj_module.getAttribute("mod_id")].push({
                        ui_left: u_min_x / ui_grid_w,
                        ui_top: u_min_y / ui_grid_w,
                        ui_width: arr_size[0] / ui_grid_w,
                        ui_height: arr_size[1] / ui_grid_w
                    });
                } else {
                    obj_box_name[obj_module.getAttribute("mod_id")] = [
                        {
                            ui_left: u_min_x / ui_grid_w,
                            ui_top: u_min_y / ui_grid_w,
                            ui_width: arr_size[0] / ui_grid_w,
                            ui_height: arr_size[1] / ui_grid_w
                        }
                    ];
                }
                if (ui_min_x > u_min_x) {
                    ui_min_x = u_min_x;
                }
                if (ui_min_y > u_min_y) {
                    ui_min_y = u_min_y;
                }
                if (ui_max_x < u_max_x) {
                    ui_max_x = u_max_x;
                }
                if (ui_max_y < u_max_y) {
                    ui_max_y = u_max_y;
                }
                ui_cnt++;
            }
        }
        var ui_w = Math.round((ui_max_x - ui_min_x) / ui_grid_w);
        var ui_h = Math.round((ui_max_y - ui_min_y) / ui_grid_w);

        if (b_screen) {
            return [ui_w, ui_h, ui_cnt, obj_box_name];
        }
        return [ui_w, ui_h];
    }
    return false;
}

// 获取模组宽高
/**
 * @param {Promise<string>} str_mod_name 模组名称
 * @param {Promise<Array>} ary_mod_data 模组数据
 * @returns {Promise<{ui_width:Number,ui_height:Number}>} 模组宽高
 *  **/
function mc_layout_get_mod_size(str_mod_name, ary_mod_data) {
    if ("string" !== typeof str_mod_name || 0 >= str_mod_name.length) {
        return false;
    }
    if (!Array.isArray(ary_mod_data) || 0 >= ary_mod_data.length) {
        return false;
    }
    var ui_mod_idx = mc_layout_get_data_idx_in_name(ary_mod_data, str_mod_name);

    if (0 !== ui_mod_idx && !ui_mod_idx) {
        return false;
    }
    var obj_sdk_module = ary_mod_data[ui_mod_idx].data;
    var obj_rect = obj_sdk_module.mc_util_mod_get_img_rect(0, 0xffffffff);
    var ui_width = (obj_rect.u32_right + 1 - obj_rect.u32_left);
    var ui_height = (obj_rect.u32_bottom + 1 - obj_rect.u32_top);
    var ary_size = [
        Number(ui_width),
        Number(ui_height)
    ];

    return ary_size;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    构造不重复数据数组
 * 参数:
 *     @param { Promise<String> } str_data 添加数据
 *     @param { Promise<Array> } ary_data 数据数组
 * 返回：
 *    @return { Promise<Boolean> }
 *     true 记录成功
 *     false 参数错误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.6.22
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_save_use_mod_name(str_data, ary_data) {
    if ("string" !== typeof str_data || 0 === str_data.length || !Array.isArray(ary_data)) {
        return ary_data;
    }
    var b_save = true;

    for (var idx = 0; idx < ary_data.length; idx++) {
        var str_name = ary_data[idx];

        if (str_data === str_name) {
            b_save = false;
            break;
        }
    }
    if (b_save) {
        ary_data.push(str_data);
    }
    return ary_data;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    判断当前元素是否存在数组对象中
 * 参数:
 *     @param { Promise<Object> } o_target 添加数据
 *     @param { Promise<Array> } ary_data 数据数组
 * 返回：
 *    @return { Promise<Boolean> }
 *     true 不存在
 *     false 参数错误/存在
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_save_use_data(o_target, ary_data) {
    if ("object" !== typeof o_target || !Array.isArray(ary_data)) {
        return false;
    }

    for (var idx = 0; idx < ary_data.length; idx++) {
        var obj_data = ary_data[idx];

        if (obj_data[0] === o_target[0]) {
            return false;
        }
    }

    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    去除未设置port/jx标识
 * 参数:
 *     @param { Promise<Object> } obj_jq 添加数据
 * 返回：
 *    @return { Promise<Boolean> }
 *     true 设置成功
 *     false 参数错误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.12
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_remove_unset_tip(obj_jq) {
    if ("[object Object]" !== Object.prototype.toString.call(obj_jq)) {
        return false;
    }
    obj_jq.removeClass("unset_module");
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    将未连线数据存入连线对象中
 * 参数:
 *     @param { Promise<Object> } obj_same_hub_queue 连线队列
 *     @param { Promise<String> } str_default_key 默认(未设置)队列key
 * 返回：
 *    @return { Promise<Object> }
 *     obj_same_hub_queue 存在未设置队列
 *     false 参数错误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.12
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_save_unset_data(obj_same_hub_queue, str_default_key) {
    if ("[object String]" !== Object.prototype.toString.call(str_default_key)) {
        return obj_same_hub_queue;
    }
    var unset_list = document.getElementsByClassName("unset_module");

    for (var i = 0; i < unset_list.length; i++) {
        var obj_jq = $(unset_list[i]);

        if (obj_same_hub_queue[str_default_key]) {
            obj_same_hub_queue[str_default_key].push(obj_jq);
        } else {
            obj_same_hub_queue[str_default_key] = [obj_jq];
        }
    }
    return obj_same_hub_queue;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    应用功能
 * 参数:
 *     @param {Promise<Object>} obj_save_data 页面数据对象
 *     @param {Promise<Array>} ary_img_data 图像数据参数
 *     @param {Promise<Array>} ary_box_data 箱体数据
 *     @param {Promise<Array>} ary_mod_data 模组数据
 * 返回：
 *     @returns{Promise<Arrray>} 保存数据
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.9.14
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_apply_data(obj_save_data, ary_img_data, ary_box_data, ary_mod_data) {
    if (
        "object" !== typeof obj_save_data ||
        0 >= Object.keys(obj_save_data)
    ) {
        return false;
    }
    var obj_screen_xml = new mc_sdk_sendcard();
    var ary_send_location = Object.keys(obj_save_data);

    mc_layout_save_set_send_list(0, ary_send_location, obj_save_data, obj_screen_xml, ary_img_data, ary_box_data, ary_mod_data, false, function (ui_error) {
        if (0 !== ui_error) {
            ary_img_data = false;
        }
    });
    return ary_img_data;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    加载配置(屏幕信息文件)
 * 参数:
 *     @param {Promise<String>} str_file_value 加载配置内容
 *     @param {Promise<Array>} ary_box_data 箱体数据
 *     @param {Promise<Array>} ary_mod_data 模组数据
 * 返回：
 *     @returns {Promise<Number>} 处理结果
 *      0:成功
 *      1:加载内容错误
 *
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.9.10
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_lod_file(str_file_value, ary_box_data, ary_mod_data) {
    var obj_screen_xml = new mc_sdk_sendcard();

    if (!obj_screen_xml.set_send_xml(str_file_value)) {
        return 1;
    }
    var arr_box_list = obj_screen_xml.get_box_list();

    var arr_all = [];

    for (var idx_box = 0; idx_box < arr_box_list.length; idx_box++) {
        var arr_set_box_name = [];
        var str_box_name = arr_box_list[idx_box].box_name;
        var str_mirror = arr_box_list[idx_box].mirror;
        var str_rotation = arr_box_list[idx_box].rotation;
        var str_scale = arr_box_list[idx_box].scale;
        var str_cut = arr_box_list[idx_box].cut;
        var str_box_data_xml = arr_box_list[idx_box].box_data;

        arr_set_box_name.push([str_box_name, str_mirror, str_rotation, str_scale, str_cut]);

        str_box_data_xml = atob(str_box_data_xml);
        var ary_char_data = str_box_data_xml.split("").map(function (str_x) {
            return str_x.charCodeAt(0);
        });
        var ary_bin_data = new Uint8Array(ary_char_data);
        var ary_data = pako.inflate(ary_bin_data);

        str_box_data_xml = "";
        for (var idx = 0; idx < ary_data.length; idx++) {
            str_box_data_xml += String.fromCharCode(ary_data[idx]);
        }

        var str_new_name = mc_main_load_msg(str_box_data_xml, ary_box_data, ary_mod_data);

        if ("string" !== typeof str_new_name) {
            mc_get_top_fun("mc_alert_popout", "MC_LANG_SAVE_ERROR_" + str_new_name);
            return str_new_name;
        }
        arr_set_box_name.push([str_new_name, str_mirror, str_rotation, str_scale, str_cut]);
        arr_all.push(arr_set_box_name);
    }

    var ary_send_list = obj_screen_xml.get_recvcard_data();
    var str_srceen_w = obj_screen_xml.get_sreen_msg_width();
    var str_srceen_h = obj_screen_xml.get_sreen_msg_height();
    var str_srceen_box_cnt = obj_screen_xml.get_sreen_msg_box_cnt();

    mc_layout_modify_set_box_name(ary_send_list, arr_all);
    var obj_return = {
        data: ary_send_list,
        width: str_srceen_w,
        height: str_srceen_h,
        box_cnt: str_srceen_box_cnt
    };

    return obj_return;
}
// 修改存入箱体名称,使用加入时创建的箱体名称
function mc_layout_modify_set_box_name(ary_send_list, ary_box_name_list) {
    if (!Array.isArray(ary_send_list) || 0 >= ary_send_list.length) {
        return;
    }
    for (var idx_list = 0; idx_list < ary_send_list.length; idx_list++) {
        // 单个数据对象
        var obj_data = ary_send_list[idx_list];

        if (!obj_data) {
            continue;
        }
        var ary_chip_list = obj_data.CHILD;

        if (obj_data.CHIP_NAME) {
            var str_box_name_file = obj_data.box_name;
            var str_mirror = obj_data.mirror;
            var str_rotation = obj_data.rotation;
            var str_scale = obj_data.scale;
            var str_cut = obj_data.cut;

            for (var idx_box_name = 0; idx_box_name < ary_box_name_list.length; idx_box_name++) {
                var ary_box_name = ary_box_name_list[idx_box_name];
                var ary_box_name_old = ary_box_name[0];
                var ary_box_name_new = ary_box_name[1];

                if (
                    ary_box_name_old[0] === str_box_name_file &&
                    ary_box_name_old[1] === str_mirror &&
                    ary_box_name_old[2] === str_rotation &&
                    ary_box_name_old[3] === str_scale &&
                    ary_box_name_old[4] === str_cut
                ) {
                    obj_data.box_name = ary_box_name_new[0];
                    break;
                }
            }
            // obj_data.box_name = "";
            // obj_data.ctrlchip = "";
        } else {
            mc_layout_modify_set_box_name(ary_chip_list, ary_box_name_list);
        }
    }
}
/********************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    查找接收卡,并将接收卡内容渲染只页面
 * 参数:
 *     @param {Promise<Array>} ary_data_list 数据列表
 *     @param {Promise<Array>} ary_rec_idx 接收卡地址数组
 *     @param {Promise<Array>} arr_box_data 箱体数据源
 *     @param {Promise<Array>} arr_mod_data 模组数据源
 * 返回：
 *     @returns {Promise<Array>} [页面渲染字符串:String,连线对象:Object]
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.9.10
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_get_rec_apply_ui(ary_data_list, ary_rec_idx, arr_box_data, arr_mod_data) {
    if (!Array.isArray(ary_data_list) || 0 >= ary_data_list.length) {
        return ["", false];
    }
    var ary_idx = ary_rec_idx.slice(0);
    var str_html = "";
    var obj_module_line = {};

    for (var idx_list = 0; idx_list < ary_data_list.length; idx_list++) {
        // 单个数据对象
        var obj_data = ary_data_list[idx_list];

        if (!obj_data) {
            continue;
        }
        // 当前数据
        var str_name_val = obj_data.NAME;
        // 下级数据列表
        var ary_chip_list = obj_data.CHILD;

        if (obj_data.ctrlchip) {
            var obj_get_html = mc_layout_apply_rec_to_ui(idx_list, obj_data, ary_idx, arr_box_data, arr_mod_data);

            str_html += obj_get_html.str_html;
            obj_module_line = obj_get_html.obj_module_line_id;
        } else {
            var ary_return = [];

            if ("SENDCARD" === str_name_val) {
                ary_return = mc_layout_get_rec_apply_ui(ary_chip_list, [idx_list], arr_box_data, arr_mod_data);
                str_html += ary_return[0];
            } else {
                ary_idx.push(idx_list);
                ary_return = mc_layout_get_rec_apply_ui(ary_chip_list, ary_idx, arr_box_data, arr_mod_data);
                str_html += ary_return[0];
                ary_idx = ary_rec_idx.slice(0);
            }
            obj_module_line = ary_return[1] ? ary_return[1] : obj_module_line;
        }
    }
    return [str_html, obj_module_line];
}
/********************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    根据接收卡数据将接收卡渲染至页面
 * 参数:
 *     @param {Promise<Number>} ui_rec_idx 接收卡位置
 *     @param {Promise<Object>} obj_data 接收卡数据
 *     @param {Promise<Array>} ary_data_idx 接收卡地址数组
 *     @param {Promise<Array>} arr_box_data 箱体数据源 与原函数调用传参一致;
 *     @param {Promise<Array>} arr_mod_data 模组数据源
 * 返回：
 *     @returns {Promise<String>} 加入箱体html字符串
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.9.10
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_apply_rec_to_ui(ui_rec_idx, obj_data, ary_data_idx, arr_box_data, arr_mod_data) {
    // 箱体名称
    var str_box_name = obj_data.box_name;
    // 箱体宽度
    var str_box_width = obj_data.vcs_orign_width;
    // 箱体高度
    var str_box_height = obj_data.vcs_orign_height;
    // 箱体x轴偏移
    var str_box_offset_x = obj_data.offset_x;
    // 箱体y轴偏移
    var str_box_offset_y = obj_data.offset_y;
    // 当前接收卡镜像表达式(默认不镜像)
    var str_box_mirror = obj_data.mirror;
    // 当前接收旋转表达式
    var str_box_rotation = obj_data.rotation;
    // 当前接收卡缩放表达式
    var str_box_scale = obj_data.scale;
    var str_box_cut = obj_data.cut || "0,0,0,0";
    // 当前接收卡主控芯片名称
    var str_ctrlchip = obj_data.ctrlchip;
    // 获取芯片名称使用保存的箱体数据源
    var ui_box_i = mc_layout_get_data_idx_in_name(arr_box_data, str_box_name);

    if ("boolean" !== typeof ui_box_i) {
        var ary_box_size = mc_layout_get_box_size(str_box_name, arr_box_data, arr_mod_data);
        var arr_box_cut = str_box_cut.split(",");

        str_ctrlchip = arr_box_data[ui_box_i].data.mc_util_get_ui_box_msg().ctrlchip_name;
        str_box_width = ary_box_size[0] - Number(arr_box_cut[0]) - Number(arr_box_cut[1]);
        str_box_height = ary_box_size[1] - Number(arr_box_cut[2]) - Number(arr_box_cut[3]);
    }

    var str_class_name = "";
    var str_rec_loc_ui_text = "";
    var str_rec_port_ui_text = "?";
    var ui_clr_rule = 0;

    if (1 !== ary_data_idx.length) {
        var ui_send_loc = (ary_data_idx[0] + 1);
        var ui_send_port_loc = (ary_data_idx[1] + 1);
        var ui_hub_loc = (ary_data_idx[2] + 1);
        var ui_hub_port_loc = (ary_data_idx[3] + 1);

        str_class_name = "mc_recvcard_box_S" + ui_send_loc + "_P" + ui_send_port_loc;
        str_rec_loc_ui_text = "S" + ui_send_loc;
        str_rec_port_ui_text = "P" + ui_send_port_loc;
        ui_clr_rule += ui_send_loc + ui_send_port_loc;
        if ("number" === typeof ary_data_idx[2] && !isNaN(ary_data_idx[2])) {
            str_class_name = "mc_recvcard_box_S" + ui_send_loc + "_P" + ui_send_port_loc + "_H" + ui_hub_loc + "_P" + ui_hub_port_loc;
            str_rec_loc_ui_text += "_P" + ui_send_port_loc + "_H" + ui_hub_loc;
            str_rec_port_ui_text = "P" + ui_hub_port_loc;
            ui_clr_rule += ui_hub_loc + ui_hub_port_loc;
        }
    }

    var obj_mod_data = {
        width: "",
        height: "",
        left: "",
        top: "",
        module_class: [],
        module_style: [],
        center_hub_val: "",
        module_id: "",
        module_list_idx: ui_rec_idx.toString(),
        module_card_idx: "",
        transform_msg: []
    };
    var arr_scale = str_box_scale.split(",");

    obj_mod_data.width = str_box_width;
    obj_mod_data.height = str_box_height;
    obj_mod_data.top = str_box_offset_y;
    obj_mod_data.left = str_box_offset_x;
    obj_mod_data.module_class = [str_class_name];
    obj_mod_data.center_hub_val = str_rec_port_ui_text;
    obj_mod_data.module_id = str_box_name;
    obj_mod_data.module_card_idx = str_rec_loc_ui_text;
    obj_mod_data.transform_msg = [arr_scale[2], arr_scale[3], str_box_rotation.split(",")[2], str_box_mirror, str_box_cut];
    obj_mod_data.ctrlchip_name = str_ctrlchip;
    obj_mod_data.module_show_name = g_obj_side_show_name.get_name("BOX", str_box_name);
    var obj_html = obj_box.get_module_html_str(obj_mod_data, obj_same_hub_queue); // eslint-disable-line

    if (0 !== str_class_name.length && 0 !== ui_clr_rule) {
        // 增加颜色
        mc_add_css_rules("theme_hl_layout", "." + str_class_name, get_bgc_css(ui_clr_rule));
    }
    return obj_html;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    保存文件
 * 参数:
 *     @param {Promise<Object>} obj_save_data 页面数据对象
 *     @param {Promise<Array>} ary_img_data 图像数据参数
 *     @param {Promise<Number>} ui_screen_w 屏幕宽度
 *     @param {Promise<Number>} ui_screen_h 屏幕高度
 *     @param {Promise<Number>} ui_screen_box_cnt 屏幕箱体数量
 *     @param {Promise<Array>} ary_box_data 箱体数据
 *     @param {Promise<Array>} ary_mod_data 模组数据
 *     @param {Promise<Boolean>} b_is_set_data 是否储存箱体数据
 *     @param {Promise<Function>} fn_callback 回调函数(xml描述字串)
 *     @param {Promise<Object>} obj_cache_box 页面缓存箱体参数
 * 返回：
 *     NA
 * 备注:
 *     0:参数错误
 *     1:芯片错误
 *     2:分组模式错误
 *     3:引脚错误
 *     4:三线并行颜色错误
 *     5:未知错误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.9.10
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_save_file(obj_save_data, ary_img_data, ui_screen_w, ui_screen_h, ui_screen_box_cnt, ary_box_data, ary_mod_data, b_is_set_data, fn_callback, obj_cache_box) {
    if (
        "object" !== typeof obj_save_data ||
        0 >= Object.keys(obj_save_data) ||
        !ary_img_data
    ) {
        fn_callback(0);
        return;
    }
    g_obj_box_data_xml_list = {};
    g_ary_box_xml_list = [];
    var obj_screen_xml = new mc_sdk_sendcard();
    var ary_send_location = Object.keys(obj_save_data);

    if (-1 !== ary_send_location.indexOf("?")) {
        ary_img_data.push({
            NAME: "?",
            CHILD: []
        });
    }
    g_obj_save_log.error("获取页面参数填入图像数据中");
    mc_layout_save_set_send_list(0, ary_send_location, obj_save_data, obj_screen_xml, ary_img_data, ary_box_data, ary_mod_data, b_is_set_data, function (ui_error) {
        if (
            0 !== ui_error
        ) {
            fn_callback(ui_error);
            return;
        }
        if (!obj_screen_xml.set_img_data(ary_img_data)) {
            fn_callback(5);
            return;
        }
        obj_screen_xml.set_sreen_msg_width(ui_screen_w.toString());
        obj_screen_xml.set_sreen_msg_height(ui_screen_h.toString());
        obj_screen_xml.set_sreen_msg_box_cnt(ui_screen_box_cnt.toString());
        obj_screen_xml.set_box_list(g_obj_box_data_xml_list);
        g_obj_box_data_xml_list = {};
        fn_callback(obj_screen_xml.get_sencdcard_xml_text());
    }, obj_cache_box);
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    查询所有端口内容,存入端口下接收卡数据
 * 参数:
 *     @param {Promise<Number>} ui_ary_idx 查询下标
 *     @param {Promise<Array>} ary_send_list 查询列表
 *     @param {Promise<Object>} obj_save_data 查询对象
 *     @param {Promise<Object>} obj_xml_screen 储存接收卡内容对象
 *     @param {Promise<Array>} ary_img_data 图像数据数组
 *     @param {Promise<Array>} ary_box_data 箱体数据
 *     @param {Promise<Array>} ary_mod_data 模组数据
 *     @param {Promise<Boolean>} b_is_set_data 是否储存箱体数据
 *     @param {Promise<Function>} fn_callback 回调函数
 *     @param {Promise<Object>} obj_cache_box 页面缓存箱体参数
 * 返回：
 *     NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.9.10
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_save_set_send_list(ui_ary_idx, ary_send_list, obj_save_data, obj_xml_screen, ary_img_data, ary_box_data, ary_mod_data, b_is_set_data, fn_callback, obj_cache_box) {
    if (!ary_img_data) {
        fn_callback(1);
        return;
    }
    var ary_set_box_list = [];

    for (var idx_send = 0; idx_send < ary_send_list.length; idx_send++) {
        var str_send_location = ary_send_list[idx_send];
        var ary_rec_list = obj_save_data[str_send_location];
        // 组合模块处理
        var o_compose_data = mc_layout_save_handle_compose(ary_rec_list[0]);
        var obj_compose_data = null;

        if (o_compose_data) {
            ary_rec_list = o_compose_data.arr_key;
            obj_compose_data = o_compose_data.obj_data;
        }

        for (var idx_rec = 0; idx_rec < ary_rec_list.length; idx_rec++) {
            var obj_item = ary_rec_list[idx_rec];
            var ary_rec_offset = [];
            var ary_rec_size = [];
            var str_box_name = "";
            var str_ctrlchip = "";
            var arr_transform = null;

            if (o_compose_data) {
                // 获取组合小块数据
                var obj_item_compose_data = obj_compose_data[obj_item];
                var arr_transform_param = obj_item_compose_data.transform_param;

                ary_rec_offset = [obj_item_compose_data.left, obj_item_compose_data.top];
                ary_rec_size = [obj_item_compose_data.width, obj_item_compose_data.height];
                str_box_name = obj_item_compose_data.name;
                str_ctrlchip = obj_item_compose_data.ctrlchip_name;
                if (0 !== arr_transform_param.length) {
                    arr_transform = [
                        false,
                        arr_transform_param[2],
                        [arr_transform_param[0], arr_transform_param[1]],
                        arr_transform_param[3]
                    ];
                }
            } else {
                var $obj_dom_recvcard = obj_item.children().eq(0);

                ary_rec_offset = $obj_dom_recvcard.children().eq(3).text().split(",");
                ary_rec_size = $obj_dom_recvcard.children().eq(2).text().split("X");
                // 箱体名称
                str_box_name = obj_item.attr("mod_id");
                // 当前接收卡主控芯片名称
                str_ctrlchip = $obj_dom_recvcard.children().eq(1).text();
                arr_transform = mc_analysis_transform_msg(obj_item[0], "all");
            }

            var ary_rec_loc = str_send_location.match(/\d+/g);
            // 箱体宽度
            var str_box_width = ary_rec_size[0];
            // 箱体高度
            var str_box_height = ary_rec_size[1];
            // 箱体x轴偏移
            var str_box_offset_x = ary_rec_offset[0];
            // 箱体y轴偏移
            var str_box_offset_y = ary_rec_offset[1];
            // 当前接收卡镜像表达式(默认不镜像)
            var str_box_mirror = "0";
            // 当前接收旋转表达式
            var str_box_rotation = "0,0,0";
            // 当前接收卡缩放表达式
            var str_box_scale = "0.0,0.0,1.0,1.0";
            // 当前接收卡裁剪表达式
            var str_box_cut = "0,0,0,0";
            // 发送卡位置
            var str_send_loc = "-1";
            // 发送卡端口位置
            var str_send_port_loc = "-1";
            // hub卡位置
            var str_hub_loc = "-1";
            // hub卡端口位置
            var str_hub_port_loc = "-1";
            var obj_set_rec_data = {};


            if (arr_transform) {
                str_box_rotation = "0,0," + arr_transform[1];
                str_box_scale = "0,0," + arr_transform[2].join(",");
                str_box_mirror = arr_transform[3];
                str_box_cut = arr_transform[4];
            }
            if ("?" === str_send_location) {
                var ary_end = ary_img_data[ary_img_data.length - 1];

                ary_end.CHILD.push({});
                obj_set_rec_data = ary_end.CHILD[ary_end.CHILD.length - 1];
            } else {
                str_send_loc = (Number(ary_rec_loc[0]) - 1) + "";
                str_send_port_loc = (Number(ary_rec_loc[1]) - 1) + "";
                // 如果存在hub卡则赋值hub卡及端口位置
                if (ary_rec_loc[2]) {
                    str_hub_loc = (Number(ary_rec_loc[2]) - 1) + "";
                    str_hub_port_loc = (Number(ary_rec_loc[3]) - 1) + "";
                }

                if ("-1" === str_hub_loc) {
                    obj_set_rec_data = ary_img_data[str_send_loc].CHILD[str_send_port_loc].CHILD[idx_rec];
                } else {
                    obj_set_rec_data = ary_img_data[str_send_loc].CHILD[str_send_port_loc].CHILD[str_hub_loc].CHILD[str_hub_port_loc].CHILD[idx_rec];
                }
            }
            var ary_cache_box = [-1, false];

            if (obj_cache_box) {
                obj_cache_box.get_trans_box(str_box_name, str_box_mirror, str_box_rotation, str_box_scale, str_box_cut);
            }
            var str_get_box_name = str_box_name + str_box_mirror + str_box_rotation + str_box_scale + str_box_cut;

            if (
                !b_is_set_data ||
                g_obj_box_data_xml_list[str_get_box_name] ||
                ary_cache_box[1]
            ) {
                if (ary_cache_box[1]) {
                    var str_cache_box = pako.gzip(ary_cache_box[0][0].data.mc_get_ui_box_xml_by_version(1), {
                        to: "string"
                    });

                    str_cache_box = btoa(str_cache_box);
                    g_obj_box_data_xml_list[str_get_box_name] = {
                        name: str_box_name,
                        mirror: str_box_mirror,
                        rotation: str_box_rotation,
                        scale: str_box_scale,
                        data: str_cache_box,
                        cut: str_box_cut
                    };
                }
            } else {
                if (-1 === ary_set_box_list.indexOf(str_get_box_name)) {
                    ary_set_box_list.push(str_get_box_name);
                    g_ary_box_xml_list.push([str_box_name, str_box_mirror, str_box_rotation, str_box_scale, str_box_cut]);
                }
            }
            obj_set_rec_data.box_name = str_box_name;
            obj_set_rec_data.ctrlchip = str_ctrlchip;
            obj_set_rec_data.vcs_orign_width = str_box_width;
            obj_set_rec_data.vcs_orign_height = str_box_height;
            obj_set_rec_data.offset_x = str_box_offset_x;
            obj_set_rec_data.offset_y = str_box_offset_y;
            obj_set_rec_data.mirror = str_box_mirror;
            obj_set_rec_data.rotation = str_box_rotation;
            obj_set_rec_data.scale = str_box_scale;
            obj_set_rec_data.cut = str_box_cut;
        }
    }

    mc_layout_get_box_xml(0, ary_box_data, ary_mod_data, fn_callback);
}


function mc_layout_get_box_xml(ui_get_idx, ary_box_data, ary_mod_data, fn_callback) {
    if (ui_get_idx >= g_ary_box_xml_list.length) {
        fn_callback(0);
        return;
    }
    var ary_get_msg = g_ary_box_xml_list[ui_get_idx];
    var str_box_name = ary_get_msg[0];
    var str_box_mirror = ary_get_msg[1];
    var str_box_rotation = ary_get_msg[2];
    var str_box_scale = ary_get_msg[3];
    var str_box_cut = ary_get_msg[4] || "0,0,0,0";

    if (g_obj_box_data_xml_list[str_box_name + str_box_mirror + str_box_rotation + str_box_scale + str_box_cut]) {
        mc_layout_get_box_xml((ui_get_idx + 1), ary_box_data, ary_mod_data, fn_callback);
        return;
    }

    mc_sdk_apply_box(str_box_name, ary_box_data, ary_mod_data, function () {
        mc_main_construct_ui_box(str_box_name, ary_box_data, ary_mod_data, function (str_box_xml) {
            if ("string" !== typeof str_box_xml) {
                // 没有箱体参数
                // fn_callback(5);
                // return;
                g_obj_box_data_xml_list[str_box_name + str_box_mirror + str_box_rotation + str_box_scale + str_box_cut] = {
                    name: str_box_name,
                    mirror: str_box_mirror,
                    rotation: str_box_rotation,
                    scale: str_box_scale,
                    cut: str_box_cut
                    // data: str_box_xml
                };
            } else {
                str_box_xml = pako.gzip(str_box_xml, {
                    to: "string"
                });
                str_box_xml = btoa(str_box_xml);
                g_obj_box_data_xml_list[str_box_name + str_box_mirror + str_box_rotation + str_box_scale + str_box_cut] = {
                    name: str_box_name,
                    mirror: str_box_mirror,
                    rotation: str_box_rotation,
                    scale: str_box_scale,
                    cut: str_box_cut,
                    data: str_box_xml
                };
            }
            mc_layout_get_box_xml((ui_get_idx + 1), ary_box_data, ary_mod_data, fn_callback);
        });
    });
}

// 应用---组合模块数据处理
function mc_layout_save_handle_compose(obj_jq) {
    if ("[object Object]" !== Object.prototype.toString.call(obj_jq)) {
        return null;
    }
    var obj_module_data = mc_judge_get_compose_data(obj_jq);

    if (obj_module_data) {
        return {
            arr_key: Object.keys(obj_module_data),
            obj_data: obj_module_data
        };
    }
    return null;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    查询端口下所有接收卡内容,存入储存对象
 * 参数:
 *     @param {Promise<String>} str_send_location 接收卡所在端口地址
 *     @param {Promise<Number>} ui_ary_idx 查询下标
 *     @param {Promise<Array>} ary_rec_list 查询列表
 *     @param {Promise<Object>} obj_xml_screen 储存接收卡内容对象
 *     @param {Promise<Array>} ary_img_data 图像数据数组
 *     @param {Promise<Array>} ary_box_data 箱体数据
 *     @param {Promise<Array>} ary_mod_data 模组数据
 *     @param {Promise<Boolean>} b_is_set_data 是否储存箱体数据
 *     @param {Promise<Function>} fn_callback 回调函数
 *     @param {Promise<Object>} obj_cache_box 页面缓存箱体参数
 * 返回：
 *     NA
 * 备注:
 *     0:成功
 *     1:参数异常
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.9.10
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_save_set_recvcard_list(str_send_location, ui_ary_idx, ary_rec_list, obj_xml_screen, ary_img_data, ary_box_data, ary_mod_data, b_is_set_data, fn_callback, obj_cache_box) {
    if (
        ui_ary_idx >= ary_rec_list.length
    ) {
        fn_callback(0);
        return;
    }
    if (!ary_img_data) {
        fn_callback(1);
        return;
    }
    g_obj_save_log.error("获取页面接收卡图像参数");
    var $obj_dom_recvcard = ary_rec_list[ui_ary_idx].children().eq(0);
    var ary_rec_loc = str_send_location.match(/\d+/g);

    var ary_rec_offset = $obj_dom_recvcard.children().eq(3).text().split(",");
    var ary_rec_size = $obj_dom_recvcard.children().eq(2).text().split("X");

    // 箱体名称
    var str_box_name = ary_rec_list[ui_ary_idx].attr("mod_id");
    // 箱体宽度
    var str_box_width = ary_rec_size[0];
    // 箱体高度
    var str_box_height = ary_rec_size[1];
    // 箱体x轴偏移
    var str_box_offset_x = ary_rec_offset[0];
    // 箱体y轴偏移
    var str_box_offset_y = ary_rec_offset[1];
    // 当前接收卡镜像表达式(默认不镜像)
    var str_box_mirror = "0";
    // 当前接收旋转表达式
    var str_box_rotation = "0,0,0";
    // 当前接收卡缩放表达式
    var str_box_scale = "0.0,0.0,1.0,1.0";
    // 当前接收卡裁剪表达式
    var str_box_cut = "0,0,0,0";
    // 当前接收卡主控芯片名称
    var str_ctrlchip = $obj_dom_recvcard.children().eq(1).text();
    // 发送卡位置
    var str_send_loc = "-1";
    // 发送卡端口位置
    var str_send_port_loc = "-1";
    // hub卡位置
    var str_hub_loc = "-1";
    // hub卡端口位置
    var str_hub_port_loc = "-1";
    var arr_transform = mc_analysis_transform_msg($obj_dom_recvcard[0], "all");

    var obj_set_rec_data = {};

    if (arr_transform) {
        str_box_rotation = "0,0," + arr_transform[1];
        str_box_scale = "0,0," + arr_transform[2].join(",");
        str_box_mirror = arr_transform[3];
        str_box_cut = arr_transform[4];
    }
    if ("?" === str_send_location) {
        var ary_end = ary_img_data[ary_img_data.length - 1];

        ary_end.CHILD.push({});
        obj_set_rec_data = ary_end.CHILD[ary_end.CHILD.length - 1];
    } else {
        str_send_loc = (Number(ary_rec_loc[0]) - 1) + "";
        str_send_port_loc = (Number(ary_rec_loc[1]) - 1) + "";
        // 如果存在hub卡则赋值hub卡及端口位置
        if (ary_rec_loc[2]) {
            str_hub_loc = (Number(ary_rec_loc[2]) - 1) + "";
            str_hub_port_loc = (Number(ary_rec_loc[3]) - 1) + "";
        }

        if ("-1" === str_hub_loc) {
            obj_set_rec_data = ary_img_data[str_send_loc].CHILD[str_send_port_loc].CHILD[ui_ary_idx];
        } else {
            obj_set_rec_data = ary_img_data[str_send_loc].CHILD[str_send_port_loc].CHILD[str_hub_loc].CHILD[str_hub_port_loc].CHILD[ui_ary_idx];
        }
    }
    var ary_cache_box = [-1, false];

    g_obj_save_log.error("存入接收卡图像数据,存入箱体参数");

    if (obj_cache_box) {
        obj_cache_box.get_trans_box(str_box_name, str_box_mirror, str_box_rotation, str_box_scale, str_box_cut);
    }

    if (!b_is_set_data ||
        g_obj_box_data_xml_list[str_box_name + str_box_mirror + str_box_rotation + str_box_scale + str_box_cut] ||
        ary_cache_box[1]
    ) {
        if (ary_cache_box[1]) {
            var str_cache_box = pako.gzip(ary_cache_box[0][0].data.mc_get_ui_box_xml_by_version(1), {
                to: "string"
            });

            str_cache_box = btoa(str_cache_box);
            g_obj_box_data_xml_list[str_box_name + str_box_mirror + str_box_rotation + str_box_scale + str_box_cut] = {
                name: str_box_name,
                mirror: str_box_mirror,
                rotation: str_box_rotation,
                scale: str_box_scale,
                data: str_cache_box,
                cut: str_box_cut
            };
        }
        obj_set_rec_data.box_name = str_box_name;
        obj_set_rec_data.ctrlchip = str_ctrlchip;
        obj_set_rec_data.vcs_orign_width = str_box_width;
        obj_set_rec_data.vcs_orign_height = str_box_height;
        obj_set_rec_data.offset_x = str_box_offset_x;
        obj_set_rec_data.offset_y = str_box_offset_y;
        obj_set_rec_data.mirror = str_box_mirror;
        obj_set_rec_data.rotation = str_box_rotation;
        obj_set_rec_data.scale = str_box_scale;
        obj_set_rec_data.cut = str_box_cut;
        mc_layout_save_set_recvcard_list(str_send_location, (ui_ary_idx + 1), ary_rec_list, obj_xml_screen, ary_img_data, ary_box_data, ary_mod_data, b_is_set_data, fn_callback, obj_cache_box);
    } else {
        mc_sdk_apply_box(str_box_name, ary_box_data, ary_mod_data, function (error_code) {
            if ("number" === typeof error_code) {
                fn_callback(error_code);
                return;
            }
            mc_main_construct_ui_box(str_box_name, ary_box_data, ary_mod_data, function (str_box_xml) {
                if ("string" !== typeof str_box_xml) {
                    fn_callback(str_box_xml);
                    return;
                }
                str_box_xml = pako.gzip(str_box_xml, {
                    to: "string"
                });
                str_box_xml = btoa(str_box_xml);
                g_obj_box_data_xml_list[str_box_name + str_box_mirror + str_box_rotation + str_box_scale + str_box_cut] = {
                    name: str_box_name,
                    mirror: str_box_mirror,
                    rotation: str_box_rotation,
                    scale: str_box_scale,
                    data: str_box_xml,
                    cut: str_box_cut
                };
                obj_set_rec_data.box_name = str_box_name;
                obj_set_rec_data.ctrlchip = str_ctrlchip;
                obj_set_rec_data.vcs_orign_width = str_box_width;
                obj_set_rec_data.vcs_orign_height = str_box_height;
                obj_set_rec_data.offset_x = str_box_offset_x;
                obj_set_rec_data.offset_y = str_box_offset_y;
                obj_set_rec_data.mirror = str_box_mirror;
                obj_set_rec_data.rotation = str_box_rotation;
                obj_set_rec_data.scale = str_box_scale;
                obj_set_rec_data.cut = str_box_cut;
                mc_layout_save_set_recvcard_list(str_send_location, (ui_ary_idx + 1), ary_rec_list, obj_xml_screen, ary_img_data, ary_box_data, ary_mod_data, b_is_set_data, fn_callback, obj_cache_box);
            });
        });
    }
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    屏幕信息是否存在
 * 参数:
 *     @param { Promise<Object> } obj_screen_data 判断对象
 *     @param { Promise<Array> } ary_screen 判断列表
 *     @param { Promise<Number> } ui_update_screen_idx 更新屏幕下标
 * 返回：
 *      @returns {Promise<Boolean>} 屏幕信息是否存在
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.9.23
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_screen_is_exist(obj_screen_data, ary_screen, ui_update_screen_idx) {
    if (!Array.isArray(ary_screen) || 0 >= ary_screen.length) {
        return false;
    }
    var ary_screen_data = obj_screen_data.data;
    var str_screen_width = obj_screen_data.width;
    var str_screen_height = obj_screen_data.height;
    var str_screen_box_cnt = obj_screen_data.box_cnt;

    for (var idx_list = 0; idx_list < ary_screen.length; idx_list++) {
        if (ui_update_screen_idx === idx_list) {
            continue;
        }
        var obj_screen_data_loc = ary_screen[idx_list];
        var ary_screen_data_loc = obj_screen_data_loc.data;
        var str_screen_width_loc = obj_screen_data_loc.width;
        var str_screen_height_loc = obj_screen_data_loc.height;
        var str_screen_box_cnt_loc = obj_screen_data_loc.box_cnt;

        if (
            str_screen_width === str_screen_width_loc &&
            str_screen_height === str_screen_height_loc &&
            str_screen_box_cnt === str_screen_box_cnt_loc &&
            mc_layout_screen_send_list_exist(ary_screen_data, ary_screen_data_loc)
        ) {
            return true;
        }
    }
    return false;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    查询两个卡列表是否相同
 * 参数:
 *     @param { Promise<Array> } ary_send_list 判断列表
 *     @param { Promise<Array> } ary_send_list_loc 判断列表
 * 返回：
 *      @returns {Promise<Boolean>} 卡列表是否相同
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.9.23
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_screen_send_list_exist(ary_send_list, ary_send_list_loc) {
    if (
        typeof ary_send_list_loc !== typeof ary_send_list ||
        (Array.isArray(ary_send_list) && ary_send_list_loc.length !== ary_send_list.length)
    ) {
        return false;
    }
    if (
        !Array.isArray(ary_send_list) &&
        typeof ary_send_list_loc === typeof ary_send_list
    ) {
        return true;
    }
    for (var idx_list = 0; idx_list < ary_send_list.length; idx_list++) {
        var obj_screen_data = ary_send_list[idx_list];
        var obj_screen_data_loc = ary_send_list_loc[idx_list];
        // 获取对比内容
        var str_type_name = obj_screen_data.NAME + "";
        var str_offset_x = obj_screen_data.X + "";
        var str_offset_y = obj_screen_data.Y + "";
        var str_width = obj_screen_data.W + "";
        var str_height = obj_screen_data.H + "";
        var ary_chip_list = obj_screen_data.CHILD;
        var str_ctrl_chip = obj_screen_data.CHIP_NAME + "";

        // 获取本地对比内容
        var str_type_name_loc = obj_screen_data_loc.NAME + "";
        var str_offset_x_loc = obj_screen_data_loc.X + "";
        var str_offset_y_loc = obj_screen_data_loc.Y + "";
        var str_width_loc = obj_screen_data_loc.W + "";
        var str_height_loc = obj_screen_data_loc.H + "";
        var ary_chip_list_loc = obj_screen_data_loc.CHILD;

        var str_data_val = str_type_name + str_offset_x + str_offset_y + str_width + str_height;
        var str_data_val_loc = str_type_name_loc + str_offset_x_loc + str_offset_y_loc + str_width_loc + str_height_loc;

        if (
            str_data_val !== str_data_val_loc ||
            !mc_layout_screen_send_list_exist(ary_chip_list, ary_chip_list_loc)
        ) {
            return false;
        }
        if (
            "string" === typeof str_ctrl_chip &&
            (
                obj_screen_data.ctrlchip !== obj_screen_data_loc.ctrlchip ||
                obj_screen_data.box_name !== obj_screen_data_loc.box_name ||
                obj_screen_data.vcs_addr !== obj_screen_data_loc.vcs_addr ||
                obj_screen_data.vcs_orign_width !== obj_screen_data_loc.vcs_orign_width ||
                obj_screen_data.vcs_orign_height !== obj_screen_data_loc.vcs_orign_height ||
                obj_screen_data.offset_x !== obj_screen_data_loc.offset_x ||
                obj_screen_data.offset_y !== obj_screen_data_loc.offset_y ||
                obj_screen_data.mirror !== obj_screen_data_loc.mirror ||
                obj_screen_data.rotation !== obj_screen_data_loc.rotation ||
                obj_screen_data.scale !== obj_screen_data_loc.scale
            )
        ) {
            return false;
        }
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    加载配置-构造芯片信息字串
 * 参数:
 *     @param { Promise<String> } str_ctrlchip_name 主控芯片name
 *     @param { Promise<String> } str_hub_name hub name
 *     @param { Promise<String> } fun_callback 回调函数
 * 返回：
 *      void
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.6.28
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_ctrlchip_hub_msg(str_ctrlchip_name, str_hub_name, fun_callback) {
    if ("string" !== typeof str_ctrlchip_name || 0 === str_ctrlchip_name.length) {
        fun_callback("");
        return;
    }
    if ("string" !== typeof str_hub_name || 0 === str_hub_name.length) {
        fun_callback("");
        return;
    }
    if ("function" !== typeof fun_callback) {
        fun_callback("");
        return;
    }
    var obj_sdk_param = new mc_sdk_param();

    obj_sdk_param.set_param_clear();
    mc_main_get_ctrlchip_list_by_sdk(function (ary_ctrlchip) {
        var str_ctrlchip_options = "";

        for (var idx = 0; idx < ary_ctrlchip.length; idx++) {
            str_ctrlchip_options += ary_ctrlchip[idx] + ",";
        }
        str_ctrlchip_options = str_ctrlchip_options.substring(0, str_ctrlchip_options.length - 1);
        obj_sdk_param.set_param_value("MC_LANG_CTRLCHIP_LIST", str_ctrlchip_name);
        obj_sdk_param.set_attr_val("MC_LANG_CTRLCHIP_LIST", "UI_TYPE", "OPTION");
        obj_sdk_param.set_attr_val("MC_LANG_CTRLCHIP_LIST", "ARRAY", str_ctrlchip_options);

        obj_sdk_param.set_param_value("MC_LANG_LABLE_HUB", str_hub_name);
        obj_sdk_param.set_attr_val("MC_LANG_LABLE_HUB", "UI_TYPE", "OPTION");

        mc_main_get_hub(str_ctrlchip_name, function (str_hub_list) {
            obj_sdk_param.set_attr_val("MC_LANG_LABLE_HUB", "ARRAY", str_hub_list);
            fun_callback(obj_sdk_param.get_json());
            return;
        });
        fun_callback("");
        return;
    });
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    加载配置-更新使用模组名数组
 * 参数:
 *     @param { Promise<Object> } obj_box_data 箱体数据
 *     @param { Promise<Array> } ary_use_mod_name 使用模组名数组
 * 返回：
 *    @return { Promise<Boolean> }
 *     true 保存成功
 *     false 参数错误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.6.28
 *      内容 : 所有代码
 ************************************************************************************************/
function get_box_use_mod_name(obj_box_data, ary_use_mod_name) {
    if ("object" !== typeof obj_box_data || !(Array.isArray(ary_use_mod_name))) {
        return false;
    }
    var obj_box_msg = obj_box_data.data.mc_util_get_ui_box_msg();

    var ary_modlist = obj_box_msg.data;

    if (0 >= ary_modlist.length) {
        return [];
    }
    var ary_mod_name = [];

    for (var mod_idx = 0; mod_idx < ary_modlist.length; mod_idx++) {
        var ary_mod = ary_modlist[mod_idx].children;

        for (var mod_name_idx = 0; mod_name_idx < ary_mod.length; mod_name_idx++) {
            var str_mod_name = ary_mod[mod_name_idx].module_name;

            ary_mod_name = mc_save_use_mod_name(str_mod_name, ary_mod_name);
        }
    }

    // 记录当前箱体使用数组
    if (0 !== ary_mod_name.length) {
        var obj_data = {
            name: obj_box_data.name,
            use_mod_name: ary_mod_name
        };

        ary_use_mod_name.push(obj_data);
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    加载配置-设置箱体数据芯片信息字串
 * 参数:
 *     @param { Promise<String> } str_ctrlchip_name 主控芯片
 *     @param { Promise<String> } str_hub_name HUB芯片
 *     @param { Promise<Array> } obj_box_data 箱体数据
 * 返回：
 *    @return { Promise<Boolean> }
 *     true 设置成功
 *     false 参数错误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.6.29
 *      内容 : 所有代码
 ************************************************************************************************/
function set_obj_box_data(str_ctrlchip_name, str_hub_name, obj_box_data) {
    if ("string" !== typeof str_ctrlchip_name || 0 === str_ctrlchip_name.length) {
        return false;
    }
    if ("string" !== typeof str_hub_name || 0 === str_hub_name.length || "object" !== typeof obj_box_data) {
        return false;
    }
    mc_ctrlchip_hub_msg(str_ctrlchip_name, str_hub_name, function (str_data) {
        obj_box_data.ctrlchip_hub_msg = str_data;
    });
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    加载配置/回读-更新数据 箱体使用模组名、箱体数据芯片信息字串
 * 参数:
 *     @param { Promise<Object> } obj_box_data 单个箱体数据
 *     @param { Promise<Array> } ary_use_mod 箱体使用模组名数据
 * 返回：
 *    @return { Promise<Boolean> }
 *     true 更新成功
 *     false 参数错误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.6.29
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_load_msg_update_data(obj_box_data, ary_use_mod) {
    if ("object" !== typeof obj_box_data) {
        return false;
    }
    if (!ary_use_mod) {
        ary_use_mod = mc_get_top_data("ARY_USE_MOD_NAME");

        if (!ary_use_mod) {
            ary_use_mod = ARY_USE_MOD_NAME;
        }
    }
    var str_ctrlchip_hub_msg = obj_box_data.ctrlchip_hub_msg;

    if (!str_ctrlchip_hub_msg) {
        var obj_box_msg = obj_box_data.data.mc_util_get_ui_box_msg();
        var str_ctrlchip_name = obj_box_msg.ctrlchip_name;
        var str_hub_name = obj_box_msg.hub_name;

        // 记录箱体使用的模组名
        get_box_use_mod_name(obj_box_data, ary_use_mod);
        // 设置箱体数据芯片信息字串
        set_obj_box_data(str_ctrlchip_name, str_hub_name, obj_box_data);
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取侧边箱体信息
 * 参数:
 *    @param {Promise<Array>} ary_data 储存箱体/模组的数组
 *    @param {Promise<String>} str_data_name 需要获取箱体/模组数据的箱体名称
 * 返回：
 *    @returns {Promise<Object>}
 *     {..} 获取成功
 *     false 参数有误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.04.30
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_side_box_data(ary_data, str_data_name) {
    if (!Array.isArray(ary_data) || 0 === ary_data.length || "string" !== typeof str_data_name) {
        return false;
    }
    var obj_box_data = {};

    for (var idx = 0; idx < ary_data.length; idx++) {
        var str_name = ary_data[idx].name;

        if (str_name === str_data_name) {
            obj_box_data = ary_data[idx];
            break;
        }
    }
    if ({} === obj_box_data) {
        return false;
    }
    return obj_box_data;
}

// 连接卡页相关----------------------------------------------------------------
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    更新连接卡页数据
 * 参数:
 *    @param {Promise<String>} str_card_name 当前card name
 *    @param {Promise<Object>} obj_data G_OBJ_WINDOW_DATA
 *    @param {Promise<Object>} obj_same_hub_queue 所有相同的hub值队列
 * 返回：
 *    @returns {Promise<Boolean>}
 *     true 更新成功
 *     false 参数有误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.8.28
 *      内容 : 所有代码
 ************************************************************************************************/
function update_box_offset_msg(str_card_name, obj_data, obj_same_hub_queue) {
    if ("string" !== typeof str_card_name || 0 === str_card_name.length) {
        return false;
    }
    if ("object" !== typeof obj_data) {
        return false;
    }
    var ary_box = $(".mc_mod");

    if (0 === ary_box.length) {
        return false;
    }
    var arr_recvcard_name = [];
    var ui_port_cnt = Number(obj_data[str_card_name].child_num) - 1;
    // 起始接收卡name数组
    var arr_recv_name = obj_data[str_card_name].recvcard_name;
    // 接收卡下标 port0:1 -> port0口下有2张接收卡
    var obj_index = {};
    var index = 0;

    var arr_key = Object.keys(obj_same_hub_queue);
    var ary_line_box = [];

    if (0 !== arr_key.length) {
        for (var port_key = 0; port_key < arr_key.length; port_key++) {
            var arr_recv = obj_same_hub_queue[arr_key[port_key]];

            for (var index_box = 0; index_box < arr_recv.length; index_box++) {
                ary_line_box.push(arr_recv[index_box]);
            }
        }
    }

    // 更新接收卡数据
    for (var idx_box = 0; idx_box < ary_line_box.length; idx_box++) {
        var obj_box = ary_line_box[idx_box];
        var arr_msg = obj_box.attr("mod_id").split(",");
        var ui_index = 0;

        if ("number" === typeof obj_index["port" + arr_msg[0]]) {
            ui_index = Number(obj_index["port" + arr_msg[0]]) + 1;
            obj_index["port" + arr_msg[0]] = ui_index;
        } else {
            obj_index["port" + arr_msg[0]] = 0;
        }
        var str_recv_name = str_card_name + "_P" + arr_msg[0] + "_R" + ui_index;
        var arr_size = obj_box.children(".mod_msg_box").children(".mod_size").text().split("X");
        var arr_pot = obj_box.children(".mod_msg_box").children(".mod_pot").text().split(",");
        var obj_param = {
            name: str_recv_name,
            width: Number(arr_size[0]),
            height: Number(arr_size[1]),
            left: Number(arr_pot[0]),
            top: Number(arr_pot[1]),
            index: ui_index,
            ctrlchip_name: arr_msg[1],
            child_type: false,
            child_num: 0,
            lang_id: "MC_LANG_RECEIVER_CARD"
        };

        arr_recvcard_name.push(str_recv_name);
        obj_data[str_recv_name] = obj_param;
    }

    // 更新port口子卡数量
    for (var idx_port = 0; idx_port <= ui_port_cnt; idx_port++) {
        var ui_port_child_cnt = Number(obj_index["port" + idx_port]) + 1;

        if (!isNaN(ui_port_child_cnt)) {
            obj_data[str_card_name + "_P" + idx_port].child_type = "RECV";
            obj_data[str_card_name + "_P" + idx_port].child_num = ui_port_child_cnt;
        } else {
            var str_child_type = obj_data[str_card_name + "_P" + idx_port].child_type;

            if ("RECV" === str_child_type) {
                obj_data[str_card_name + "_P" + idx_port].child_type = "CHILD";
                obj_data[str_card_name + "_P" + idx_port].child_num = 0;
            }
        }
    }

    // 全部为创建接收卡情况
    if (!arr_recv_name) {
        var str_recvcard = "recvcard_name";

        obj_data[str_card_name][str_recvcard] = arr_recvcard_name;
        return true;
    }

    // 匹配当前接收卡与起始接收卡 起始接收卡不存在当前 从数据中删除
    while (index < arr_recv_name.length) {
        var b_save = false;

        for (var idx = 0; idx < arr_recvcard_name.length; idx++) {
            if (arr_recvcard_name[idx] === arr_recv_name[index]) {
                index++;
                b_save = true;
                break;
            }
        }
        if (!b_save) {
            obj_data[arr_recv_name[index]] = null;
            index++;
        }
    }

    // 更新卡下所有接收卡name数组
    obj_data[str_card_name].recvcard_name = arr_recvcard_name;
    return true;
}

/******************************************大屏相关***********************************************/
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    构造大屏快速布局字串
 * 参数:
 *     NA
 * 返回：
 *     @returns {Promise<String>}
 *      大屏快速布局JSON字串
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.4
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_screen_layout_json() {
    var arr_param_name = ["MC_LANG_ROW", "MC_LANG_COL"];
    var obj_sdk_param = new mc_sdk_param();

    obj_sdk_param.set_param_clear();

    for (var idx = 0; idx < arr_param_name.length; idx++) {
        var str_param_name = arr_param_name[idx];

        obj_sdk_param.set_param_value(str_param_name, "1");
        obj_sdk_param.set_attr_val(str_param_name, "UI_TYPE", "STEP_EDIT");
        obj_sdk_param.set_attr_val(str_param_name, "VAL_TYPE", "uint");
        obj_sdk_param.set_attr_val(str_param_name, "MIN_VAL", "1");
        obj_sdk_param.set_attr_val(str_param_name, "STEP", "1");
    }
    return obj_sdk_param.get_json();
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    构造设置发送卡、hub卡以及对应的port 弹出菜单字串
 * 参数:
 *     NA
 * 返回：
 *     @returns {Promise<String>}
 *      var obj_json = {
 *       obj_sendc: 选择发送卡json字串,
 *       obj_hubc: 使用hub卡json字串
 *      };
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.4
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_setcard_menu_json() {
    var arr_sendcard_list = mc_get_top_data("g_obj_sendcard_data").get_sendcard_list();
    var str_toggle = "1";

    if (arr_sendcard_list.length && -1 === arr_sendcard_list[0].recvcard_idx.split(",")[0].indexOf("|")) {
        str_toggle = "0";
    }
    var obj_sdk_param = new mc_sdk_param();
    var obj_sdk_param_hub = new mc_sdk_param();
    var str_param_name = "MC_LANG_BTN_SCREEN_SENDING_CARD";

    obj_sdk_param.set_param_clear();
    obj_sdk_param_hub.set_param_clear();

    obj_sdk_param.set_param_value(str_param_name, "1");
    set_step(obj_sdk_param, str_param_name);
    str_param_name = "MC_LANG_RECEIVER_SENDCARD_PORT";
    set_step(obj_sdk_param, str_param_name);

    str_param_name = "MC_LANG_USED_HUB";
    obj_sdk_param.set_param_value(str_param_name, str_toggle);
    obj_sdk_param.set_attr_val(str_param_name, "UI_TYPE", "TOGGLE");
    obj_sdk_param.set_attr_val(str_param_name, "SWITCH_TEXT", "YES,NO");

    // str_param_name = "MC_LANG_SPLIT";
    // obj_sdk_param.set_param_value(str_param_name, "0");
    // obj_sdk_param.set_attr_val(str_param_name, "UI_TYPE", "TOGGLE");
    // obj_sdk_param.set_attr_val(str_param_name, "SWITCH_TEXT", "YES,NO");

    str_param_name = "MC_LANG_HUB_CARD";
    set_step(obj_sdk_param_hub, str_param_name);
    str_param_name = "MC_LANG_HUB_PORT";
    set_step(obj_sdk_param_hub, str_param_name);

    function set_step(o_sdk_param, s_param_name) {
        o_sdk_param.set_param_value(s_param_name, "1");
        o_sdk_param.set_attr_val(s_param_name, "UI_TYPE", "STEP_EDIT");
        o_sdk_param.set_attr_val(s_param_name, "VAL_TYPE", "uint");
        o_sdk_param.set_attr_val(s_param_name, "MIN_VAL", "1");
        o_sdk_param.set_attr_val(s_param_name, "STEP", "1");
    }
    var obj_json = {
        obj_sendc: obj_sdk_param.get_json(),
        obj_hubc: obj_sdk_param_hub.get_json()
    };

    return obj_json;
}


// -------------------------------------------选中菜单相关-----------------------------------------
// 鼠标点击位置对象数组及最大层叠数
var arr_offset_same_data = null;
// 当前预选中层叠数
var ui_select_stackitem_num = 1;
// 菜单栏修改模块宽高编辑框{id:{type:"w",obj_edit:obj}, id:{type:"H",obj_edit:obj}}
// var obj_menu_size_edit = {};
// 当前菜单所在模块
var obj_menu_open_target = null;


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取选中菜单构造函数设置参数对象
 * 参数:
 *     @param {Promise<Boolean>} b_screen 是否在大屏页
 * 返回：
 *     @returns {Promise<Object>}
 *      obj_select_menu
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.11.17
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_select_menu() {
    var str_edit_icon = "";

    if (b_add_screen) {
        str_edit_icon = "icon-box-connect";
    } else {
        str_edit_icon = "icon-mod";
    }
    // 选中菜单栏对象
    var obj_select_menu = {
        target: null,
        //是否需要图标
        hasIcon: true,
        //是否自动隐藏右键菜单
        autoHide: false,
        //是否使用外链样式
        linkClass: false,
        // 是否横向摆放项
        directionRow: true,
        // 限制显示条件函数
        // limitFn: mc_limit_menu,
        // 设置触发方式为鼠标左键 事件为鼠标抬起
        LeftKeyTrigger: true,
        menuItemBox: true,
        releaseNoClose: true,
        afterHide: mc_menu_hideback,
        beforeShow: mc_menu_beforeshow,
        undefineLocation: true,
        customPackage: mc_menu_custom_package,
        //菜单项配置
        menu: {
            items: [
                {
                    // 定位
                    icon: "icon-position",
                    lang_id: "MC_LANG_POSITIONING",
                    action: mc_lang_positioning_module
                },
                {
                    // 锁定
                    icon: "icon-lock",
                    lang_id: "MC_LANG_LOCK",
                    action: mc_lang_lock_mod
                },
                {
                    // 变换
                    icon: "icon-transfer",
                    lang_id: "MC_LANG_TRANSFORMATION",
                    action: mc_lang_transformation_module
                },
                {
                    // 连线
                    icon: "icon-ligatrue",
                    lang_id: "MC_LANG_LIGATURE",
                    action: mc_lang_ligature_module
                },
                {
                    // 编辑
                    icon: str_edit_icon,
                    lang_id: "MC_LANG_EDIT",
                    action: mc_lang_edit_mod
                },
                {
                    // 删除
                    icon: "icon-close",
                    lang_id: "MC_LANG_DELETE",
                    action: mc_lang_delete_module
                },
                "rowbox",
                {
                    icon: "icon-arrow-single-left",
                    lang_id: "MC_LANG_SELECT_PREV_ONE",
                    //菜单项单击触发事件
                    action: function () {
                        mc_menu_stack_action(-1);
                    }
                },
                {
                    icon: "icon-arrow-single-right",
                    lang_id: "MC_LANG_SELECT_NEXT_ONE",
                    action: function () {
                        mc_menu_stack_action(1);
                    }
                },
                {
                    // 选中当前偏移相同模块
                    content: "All",
                    lang_id: "MC_LANG_CASCADE_SELECT_ALL",
                    action: function () {
                        mc_menu_stack_action(false, true);
                    }
                },
                // 分割线
                "-",
                {
                    // 行选
                    icon: "icon-select_line rotate_90",
                    lang_id: "MC_LANG_LINE_SELECTM",
                    action: function () {
                        if ("function" === typeof mc_select_ranks) {
                            mc_select_ranks("Y");
                        }
                    }
                },
                {
                    // 列选
                    icon: "icon-select_line",
                    lang_id: "MC_LANG_COLUMN_SELECT",
                    action: function () {
                        if ("function" === typeof mc_select_ranks) {
                            mc_select_ranks("X");
                        }
                    }
                },
                {
                    // 全选
                    icon: "icon-choose_all",
                    lang_id: "MC_LANG_FEEDBACK_ISSUE_SELECTALL",
                    action: function () {
                        if ("function" === typeof select_all_operation) {
                            select_all_operation();
                        }
                    }
                },
                {
                    // 取消选中
                    icon: "icon-cardselect",
                    lang_id: "MC_LANG_DESELECT",
                    action: function () {
                        if ("function" === typeof mc_lang_deselect_mod) {
                            mc_lang_deselect_mod();
                        }
                    }
                },
                "-",
                {
                    // 拆分
                    icon: "icon-rectify",
                    lang_id: "MC_LANG_HUB_SPLIT",
                    action: mc_compose_split_apply
                },
                {
                    // 组合编辑
                    icon: "icon-cardselect",
                    lang_id: "MC_LANG_COMPOSE_EDIT",
                    action: mc_compose_edit
                }
            ]
        }
    };

    return obj_select_menu;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    添加选择菜单 显示层叠项标签
 * 参数:
 *     @param {Promise<Object>} obj_lang_map 语言列表对象
 *     @param {Promise<Boolean>} b_screen true 大屏页面
 * 返回：
 *     @returns {Promise<Boolean>}
 *      true 设置成功
 *      false 参数有误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.11.20
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_select_stackitem(obj_lang_map) {
    if ("object" !== typeof obj_lang_map) {
        return false;
    }
    var obj_menu = $(".mc_menu_box")[0];

    // 层叠选中添加显示隐藏样式
    $(".menu_item_box").children('*[lang_id="MC_LANG_SELECT_PREV_ONE"]').addClass("mc_menu_display");
    $(".menu_item_box").children('*[lang_id="MC_LANG_SELECT_NEXT_ONE"]').addClass("mc_menu_display");
    $(".menu_item_box").children('*[lang_id="MC_LANG_CASCADE_SELECT_ALL"]').addClass("mc_menu_display");
    $(".menu_item_box").children('*[lang_id="MC_LANG_EDIT"]').addClass("mc_edit_display");
    // 组合相关按钮
    $(".menu_item_box").children('*[lang_id="MC_LANG_HUB_SPLIT"]').addClass("mc_menu_display mc_menu_compose_display");
    $(".menu_item_box").children('*[lang_id="MC_LANG_COMPOSE_EDIT"]').addClass("mc_menu_display mc_menu_compose_display mc_menu_compose_edit");

    if (0 !== obj_menu.length) {
        var str_stack_tip = "<div class='menu_stack_tip'><span class='total_sum' lang_id='MC_LANG_MAX_NUM_LAYERS'></span><span class='select_sum' lang_id='MC_CURRENT_SELECT_LAYER'></span><span class='select_msg' lang_id='MC_LANG_SELECT_MODULE_INFORMATION'></span></div>";

        obj_menu.style.flexDirection = "column";
        $(obj_menu).append(str_stack_tip);
    }
    return true;
}


// 功能限制函数------------------------------
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    限制显示条件函数 记录当前菜单所在位置模块
 * 参数:
 *     @param {Promise<Object>} o_e 鼠标事件对象
 * 返回：
 *     @returns {Promise<Boolean>}
 *      true 在显示菜单范围中
 *      false 不在
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.11.18
 *      内容 : 所有代码
 ************************************************************************************************/
// function mc_limit_menu(o_e) {
//     if ("object" !== typeof o_e) {
//         return false;
//     }
//     // 点击菜单栏保持打开
//     if (-1 !== o_e.target.parentNode.className.indexOf("menu_")) {
//         return 1;
//     }
//     // 设置大小编辑框保持菜单打开
//     // if (obj_menu_size_edit[o_e.target.id]) {
//     //     return 1;
//     // }
//     if (-1 !== o_e.target.className.indexOf("selected")) {
//         obj_menu_open_target = o_e.target;
//         return true;
//     }
//     if (-1 !== o_e.target.className.indexOf("mc_lock")) {
//         obj_menu_open_target = o_e.target;
//         return true;
//     }
//     if (-1 !== o_e.target.parentNode.parentNode.className.indexOf("selected")) {
//         obj_menu_open_target = o_e.target.parentNode.parentNode;
//         return true;
//     }
//     if (-1 !== o_e.target.parentNode.parentNode.className.indexOf("mc_lock")) {
//         obj_menu_open_target = o_e.target.parentNode.parentNode;
//         return true;
//     }
//     if (-1 !== o_e.target.parentNode.className.indexOf("selected")) {
//         obj_menu_open_target = o_e.target.parentNode;
//         return true;
//     }
//     if (-1 !== o_e.target.parentNode.className.indexOf("mc_lock")) {
//         obj_menu_open_target = o_e.target.parentNode;
//         return true;
//     }
//     obj_menu_open_target = null;
//     return false;
// }

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    选择菜单隐藏回调
 * 参数:
 *     NA
 * 返回：
 *     NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.11.20
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_menu_hideback() {
    if (arr_offset_same_data) {
        update_stackitem_txt(false, false, true);
    }
    // mc_set_size_edit_display("none");
    arr_offset_same_data = null;
    ui_select_stackitem_num = 1;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    选择菜单显示前动作
 * 参数:
 *     无
 * 返回：
 *     NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.11.28
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_menu_beforeshow() {
    mc_menu_hideback();
    // 当前若多选不显示选中上下按钮
    var len = arr_mod_selected.length;
    var b_judge_compose_btn = false;

    document.getElementsByClassName("mc_menu_box")[0].style.pointerEvents = "auto";

    if (1 >= len) {
        $(".mc_menu_display").css("display", "flex");
        b_judge_compose_btn = true;
        if (1 === len && "mc_new_box" !== arr_mod_selected[0].attr("mod_id")) {
            $(".mc_edit_display").css("display", "flex");
        } else {
            $(".mc_edit_display").css("display", "none");
        }
    } else {
        $(".mc_menu_display").css("display", "none");
        $(".mc_edit_display").css("display", "none");
    }
    // 单选判断是否显示组合相关按钮
    if (b_judge_compose_btn) {
        var obj_jq = arr_mod_selected[0];

        if (mc_judge_is_compose_module(obj_jq)) {
            $(".mc_menu_compose_display").css("display", "flex");
        } else {
            $(".mc_menu_compose_display").css("display", "none");
        }
        if (obj_jq.hasClass("compose_edit")) {
            $(".mc_menu_compose_edit").css("display", "flex");
        }
    }
    return;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    框选结束显示菜单项
 * 参数:
 *     @param {Promise<Object>} obj_js 选中元素
 * 返回：
 *     @returns {Promise<Boolean>}
 *      true
 *      false 参数有误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.05.07
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_select_end_show_menu(obj_js) {
    if ("[object HTMLDivElement]" !== Object.prototype.toString.call(obj_js)) {
        return false;
    }
    var obj_menu = document.getElementsByClassName("mc_menu_box")[0];

    if (obj_menu && "none" === obj_menu.style.display) {
        var obj_getBoundingClientRect = obj_js.getBoundingClientRect();

        mc_menu_beforeshow();
        obj_menu.style.display = "flex";
        obj_menu.style.left = obj_getBoundingClientRect.left + "px";
        obj_menu.style.top = obj_getBoundingClientRect.top + "px";
    }
    return true;
}

// 层叠选中相关-----------------------------
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    上下选择层叠模块 - 更新显示、选中指定层
 * 参数:
 *     @param {Promise<Number>} ui_compare 1选择下一个 -1选择上一个
 *     @param {Promise<Boolean>} b_all_select 全选
 * 返回：
 *     @returns {Promise<Boolean>}
 *      true 设置成功
 *      false 参数有误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.11.20
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_menu_stack_action(ui_compare, b_all_select) {
    // 获取层叠数据----
    if (!arr_offset_same_data && "function" === typeof mc_get_mouse_pot_module) {
        var obj_menu_pot = obj_page_mouse_pot.obj_pot;

        arr_offset_same_data = mc_get_mouse_pot_module(obj_menu_pot);
        update_stackitem_txt(arr_offset_same_data[1], ui_select_stackitem_num);
    }
    if (!arr_offset_same_data) {
        return false;
    }

    // 全选----
    if (b_all_select) {
        // 隐藏、初始化层提示
        mc_select_specify_stack(arr_offset_same_data[0], false, true);
        update_stackitem_txt(false, false, true);
        ui_select_stackitem_num = 1;
        return true;
    }
    if (1 === arr_offset_same_data[0].length) {
        update_stackitem_txt(false, 1);
        return true;
    }

    // 选中层---
    if ("number" !== typeof ui_compare) {
        return false;
    }
    var ui_check = ui_select_stackitem_num + ui_compare;

    if (ui_check <= arr_offset_same_data[1] && 0 !== ui_check) {
        ui_select_stackitem_num = ui_check;
        update_stackitem_txt(false, ui_select_stackitem_num);
        // 选中层
        mc_select_specify_stack(arr_offset_same_data[0], ui_check);
    }
    return true;
}


// 点击模块时 鼠标位置
function mc_mouse_pot() {
    this.obj_pot = { x: 0, y: 0 };

    this.set_pot = function (obj_pot) {
        if ("[object Object]" !== Object.prototype.toString.call(obj_pot)) {
            return false;
        }
        this.obj_pot = obj_pot;
        return true;
    };
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    设置鼠标位置
 * 参数:
 *     @param {Promise<Object>} obj_pot {x:"",y:""}
 * 返回：
 *     @returns {Promise<Boolean>}
 *      true 设置成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.5.27
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_set_mouse_pot(obj_pot) {
    var arr_key = Object.keys(obj_pot);
    var o_pot = {};

    for (var i = 0; i < arr_key.length; i++) {
        var key = arr_key[i].toLowerCase();
        var item = obj_pot[arr_key[i]];

        o_pot[key] = item;
    }
    obj_page_mouse_pot.set_pot(o_pot);
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    层叠标签 显示修改
 * 参数:
 *     @param {Promise<Number>} ui_total 最大层数
 *     @param {Promise<Number>} ui_item 当前层数
 *     @param {Promise<Boolean>} b_hide 是否隐藏标签
 * 返回：
 *     @returns {Promise<Boolean>}
 *      true 设置成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.11.20
 *      内容 : 所有代码
 ************************************************************************************************/
function update_stackitem_txt(ui_total, ui_item, b_hide) {
    // var obj_tip = document.getElementsByClassName("menu_stack_tip")[0];
    var obj_total = document.getElementsByClassName("total_sum")[0];
    var obj_select = document.getElementsByClassName("select_sum")[0];
    var arr_txt = [];

    if (b_hide) {
        // obj_tip.style.display = "none";
        obj_total.style.display = "none";
        obj_select.style.display = "none";
        // return true;
    } else {
        // obj_tip.style.display = "block";
        obj_total.style.display = "inline-block";
        obj_select.style.display = "inline-block";
        if (ui_total && !isNaN(ui_total)) {
            arr_txt = obj_total.innerText.split(":");
            obj_total.innerText = arr_txt[0] + ":" + ui_total + ",";
        }
        if (ui_item && !isNaN(ui_item)) {
            arr_txt = obj_select.innerText.split(":");
            obj_select.innerText = arr_txt[0] + ":" + ui_item + ",";
        }
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    更新当前选中模块信息
 * 参数:
 *     @param {Promise<Array>} arr_boundary 选中模块边界信息
 * 返回：
 *     @returns {Promise<Boolean>}
 *      true 设置成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.7.14
 *      内容 : 所有代码
 ************************************************************************************************/
function update_select_module_msg(arr_boundary) {
    if ("[OBJECT ARRAY]" !== Object.prototype.toString.call(arr_boundary).toUpperCase()) {
        return false;
    }
    var obj_select_msg = document.getElementsByClassName("select_msg")[0];

    if (0 === arr_boundary.length) {
        obj_select_msg.style.display = "none";
        return false;
    }
    if ("[OBJECT HTMLSPANELEMENT]" === Object.prototype.toString.call(obj_select_msg).toUpperCase()) {
        var ui_grid_w = Number(document.getElementById("mod_box_next").getAttribute("grid_w"));
        var arr_txt = obj_select_msg.innerText.split(":");

        obj_select_msg.style.display = "inline-block";
        obj_select_msg.innerText = arr_txt[0] + ":" +
            (arr_boundary[0] / ui_grid_w) + ":" + (arr_boundary[1] / ui_grid_w) + ":" + ((arr_boundary[2] - arr_boundary[0]) / ui_grid_w) + ":" + ((arr_boundary[3] - arr_boundary[1]) / ui_grid_w);
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取选中模块中最小宽高值 => (只选中一项时 返回截取信息)
 * 参数:
 *     @param {Promise<Array>} arr_select 选中模块jq数组
 * 返回：
 *     @returns {Promise<Boolean>}
 *      [ui_min_w,ui_min_h]
 *      false 参数有误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.17
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_module_min_size(arr_select) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_select)) {
        return false;
    }
    var ui_min_w = Math.pow(2, 32);
    var ui_min_h = Math.pow(2, 32);
    var str_cut = false;

    for (var i = 0; i < arr_select.length; i++) {
        var obj_js = arr_select[i][0];
        var ui_w = Number(obj_js.getAttribute("mod_wg"));
        var ui_h = Number(obj_js.getAttribute("mod_hg"));

        if (ui_min_w > ui_w) {
            ui_min_w = ui_w;
        }
        if (ui_min_h > ui_h) {
            ui_min_h = ui_h;
        }
    }
    if (1 === arr_select.length) {
        str_cut = mc_analysis_transform_msg(arr_select[0][0], "cut");
    }
    return {
        arr_min_size: [ui_min_w, ui_min_h],
        str_cut_msg: str_cut
    };
}

// 菜单动作---------------------------------
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    移动菜单
 * 参数:
 *     @param {Promise<Number>} u_l 拖拽跟随移动时传入 当前点击元素中心位置X坐标
 *     @param {Promise<Number>} u_t 拖拽跟随移动时传入 当前点击元素中心位置Y坐标
 * 返回：
 *     @returns {Promise<Boolean>}
 *      true 设置成功
 *      false 参数有误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.11.28
 *      内容 : 所有代码
 ************************************************************************************************/
function menu_move(u_l, u_t) {
    var obj_menu = $(".mc_menu_row");
    var ui_l = 0;
    var ui_t = 0;
    var ui_canvas_l = document.getElementById("mc_hlever_layout_canvas").offsetLeft;
    var ui_canvas_t = document.getElementById("mc_hlever_layout_canvas").offsetTop;
    // 控制滚动条
    var obj_scroll_box = $(".mc_mod_box").parent();
    var ui_menu_l = obj_scroll_box.scrollLeft();
    var ui_menu_t = obj_scroll_box.scrollTop();

    if ("number" === typeof ui_l && "number" === typeof u_t) {
        ui_l = u_l + ui_canvas_l - ui_menu_l;
        ui_t = u_t + ui_canvas_t - ui_menu_t;
    } else {
        // 当前背景缩放倍数
        var ui_box_scale = get_box_scale_multiple();

        ui_box_scale /= 100;
        ui_l = (obj_menu_open_target.offsetLeft + obj_menu_open_target.offsetWidth / 2) * ui_box_scale + ui_canvas_l - ui_menu_l;
        ui_t = (obj_menu_open_target.offsetTop + obj_menu_open_target.offsetHeight / 2) * ui_box_scale + ui_canvas_t - ui_menu_t;
    }

    if (obj_menu) {
        obj_menu.css({
            "left": ui_l + "px",
            "top": ui_t + "px"
        });
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    关闭右键菜单
 * 参数:
 *     无
 * 返回：
 *     @returns {Promise<Boolean>}
 *      true 设置成功
 *      false 参数有误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.11.28
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_close_menu() {
    var obj_menu = $(".mc_menu_row");

    if (obj_menu) {
        obj_menu.css("display", "none");
    }
    return true;
}

// -------------------------------------------连线------------------------------------------------
// 反向连线
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取连线数据的key
 * 参数:
 *     @param {Promise<Boolean>} b_screen 是否在大屏连接
 *     @param {Promise<Object>} obj_jq 选中jq对象
 *     @param {Promise<String>} str_key 中心标识text
 * 返回：
 *     @returns {Promise<String>}
 *      false 参数有误
 *      str_keys
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.8
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_line_key(b_screen, obj_jq, str_key) {
    if ("boolean" !== typeof b_screen) {
        return false;
    }
    if ("string" !== typeof str_key || 0 === str_key.length) {
        return false;
    }
    var str_keys = "";

    if (b_screen) {
        var obj_card_idx = mc_get_appoint_obj(obj_jq, "card_idx");

        if (!obj_card_idx) {
            return false;
        }
        if ("" === obj_card_idx.innerHTML) {
            str_keys = str_key;
        } else {
            str_keys = obj_card_idx.innerHTML + ":" + str_key;
        }
    } else {
        str_keys = str_key;
    }
    return str_keys;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    反向连线数据判断
 * 参数:
 *     @param {Promise<Array>} arr_order 待处理数据
 *     @param {Promise<String>} str_key 当前数据key
 *     @param {Promise<Boolean>} b_screen 是否在大屏连接
 * 返回：
 *     @returns {Promise<Array>}
 *      false 参数有误
 *      arr_reverse 排列完成数组
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.9
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_reverse_line_arrow_data(arr_order, str_key, b_screen) {
    if ((!Array.isArray(arr_order)) || 0 === arr_order.length) {
        return false;
    }
    if ("string" !== typeof str_key || 0 === str_key.length) {
        return false;
    }
    var select_list = $(".selected");
    var arr_reverse = [];

    if (1 === select_list.length) {
        arr_reverse = select_one_reverse(arr_order);
    } else {
        var arr_cnt = [];

        // 判断当前选中在同个PORT数量
        for (var idx_item = 0; idx_item < select_list.length; idx_item++) {
            var obj_item = select_list.eq(idx_item);
            var str_id = "";

            if (b_screen) {
                str_id = mc_get_appoint_obj(obj_item, "card_idx", true).text() + ":" + obj_item.children(".mod_hub_box").children(".mod_hub_div").text();
            } else {
                str_id = obj_item.children(".mod_hub_box").children(".mod_hub_div").text();
            }

            if (str_id === str_key) {
                arr_cnt.push(obj_item);
            }
        }
        if (1 === arr_cnt.length) {
            arr_reverse = select_one_reverse(arr_order);
        } else if (arr_cnt.length === arr_order.length) {
            // 全选直接反向
            arr_reverse = select_one_reverse(arr_order);
        } else {
            if (2 === arr_cnt.length) {
                // 选中首尾不改变连线方向
                var str_check_id = arr_cnt[0].attr("id") + "_" + arr_cnt[1].attr("id");
                var str_check_id2 = arr_cnt[1].attr("id") + "_" + arr_cnt[0].attr("id");

                if (0 === $("#" + str_check_id).length && 0 === $("#" + str_check_id2).length) {
                    return arr_order;
                }
            }

            arr_reverse = mc_line_construct_block(arr_cnt, arr_order);
        }
    }

    return arr_reverse;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    反向连线数据处理 排列 -> 分类连线数据块 包含处理可能选中不连续块情况
 * 参数:
 *     @param {Promise<Array>} arr_cnt 当前在同个PORT下选中的元素
 *     @param {Promise<Array>} arr_order 此PORT下连线顺序元素
 * 返回：
 *     @returns {Promise<Array>}
 *      false 参数有误
 *      arr_reverse 排列完成数组
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.10
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_line_construct_block(arr_cnt, arr_order) {
    if ((!Array.isArray(arr_cnt)) || 0 === arr_cnt.length) {
        return false;
    }
    if ((!Array.isArray(arr_order)) || 0 === arr_order.length) {
        return false;
    }
    // 按元素在连线数组中顺序摆放
    var arr_pot = [];

    for (var idx_cnt = 0; idx_cnt < arr_cnt.length; idx_cnt++) {
        var obj_cnt = arr_cnt[idx_cnt];
        var index = 0;

        while (obj_cnt[0] !== arr_order[index][0] && index < arr_order.length) {
            index++;
        }
        arr_pot[index] = (arr_order[index]);
    }

    // 分组元素
    var arr_group = [];
    var arr_group_item = [];
    // 每组元素在数据中最近位置
    var arr_min_pot = [];
    var ui_min_pot = Math.pow(2, 32) - 1;
    var ui_save_idx = -1;

    // 分组块 相邻连线块为一组
    for (var idx_block = 0; idx_block < arr_pot.length; idx_block++) {
        var obj_block = arr_pot[idx_block];

        if (("object" === typeof obj_block && (ui_save_idx - 1 === idx_block || ui_save_idx + 1 === idx_block)) || ("object" === typeof obj_block && 0 === arr_group_item.length)) {
            arr_group_item.push(obj_block);
            ui_save_idx = idx_block;
            if (idx_block < ui_min_pot) {
                ui_min_pot = idx_block;
            }
        } else if (0 !== arr_group_item.length) {
            arr_group.push(arr_group_item);
            arr_min_pot.push(ui_min_pot);
            arr_group_item = [];
            ui_min_pot = Math.pow(2, 32) - 1;
        }
    }

    if (0 !== arr_group_item.length) {
        arr_group.push(arr_group_item);
        arr_min_pot.push(ui_min_pot);
    }

    for (var idx_group = 0; idx_group < arr_group.length; idx_group++) {
        if (1 === arr_group[idx_group].length) {
            continue;
        }
        // 反向数据
        arr_group[idx_group] = select_one_reverse(arr_group[idx_group]);
        for (var idx_data = 0; idx_data < arr_group[idx_group].length; idx_data++) {
            // 处理完成数据插入原数组
            arr_order[arr_min_pot[idx_group] + idx_data] = arr_group[idx_group][idx_data];
        }
    }
    return arr_order;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    反向排列数组数据
 * 参数:
 *     @param {Promise<Array>} arr_data 数据
 * 返回：
 *     @returns {Promise<Array>}
 *      false 参数有误
 *      arr_reverse 排列完成数组
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.9
 *      内容 : 所有代码
 ************************************************************************************************/
function select_one_reverse(arr_data) {
    if (!(Array.isArray(arr_data)) || 0 === arr_data.length) {
        return false;
    }
    var ary_reverse = [];

    for (var idx = 0; idx < arr_data.length; idx++) {
        ary_reverse.unshift(arr_data[idx]);
    }
    return ary_reverse;
}

// 手动连线
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    构造合并队列 还未存在手动连线队列数据
 * 参数:
 *     @param {Promise<Array>} arr_hub 当前对应数据队列
 *     @param {Promise<Array>} arr_manual_connection 当前手动连线
 * 返回：
 *     @returns {Promise<Boolean>}
 *      false 参数错误
 *      arr_concat
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.17
 *      内容 : 所有代码
 ************************************************************************************************/
function get_concat(arr_hub, arr_manual_connection) {
    if (!Array.isArray(arr_hub) || !Array.isArray(arr_manual_connection)) {
        return false;
    }
    var arr_concat = [];

    for (var idx_concat = 0; idx_concat < arr_hub.length; idx_concat++) {
        var b_add = true;

        for (var idx_connection = 0; idx_connection < arr_manual_connection.length; idx_connection++) {
            if (arr_hub[idx_concat][0] === arr_manual_connection[idx_connection][0]) {
                b_add = false;
                continue;
            }
        }
        if (b_add) {
            arr_concat[idx_concat] = arr_hub[idx_concat];
        }
    }

    // 去除空项
    arr_concat = mc_filter_tool(function (item) {
        return "[object Undefined]" !== Object.prototype.toString.call(item);
    }, arr_concat);
    return arr_concat;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    重置手动连线设置
 * 参数:
 *     NA
 * 返回：
 *     NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.10.22
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_reset_manual_connection() {
    var elem_iframe = document.getElementsByTagName("iframe");

    for (var idx = 0; idx < elem_iframe.length; idx++) {
        var fn_lang_chg = elem_iframe[idx].contentWindow.mc_subpage_popout_confirm_close;

        if (fn_lang_chg) {
            fn_lang_chg();
        }
    }
}


// 快速连线
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取水平排列数据
 * 参数:
 *     @param {Promise<Array>} arr_mod 当前选中元素
 *     @param {Promise<Array>} b_supply 布局连线时补充数据true 可为空
 * 返回：
 *     @returns {Promise<Boolean>}
 *      false 参数错误
 *      arr_row 多维数组 每项为一行数据 每行元素从左到右排列
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.18
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_quick_connect_row_data(arr_mod, b_supply) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_mod) || 0 === arr_mod.length) {
        return false;
    }
    // 获取显示数据
    var obj_base_msg = mc_get_child_pot_size(arr_mod[0][0]);
    var ui_base_top = Number(obj_base_msg.str_pot.split(",")[1]);
    var ui_base_h = Number(obj_base_msg.str_size.split("X")[1]);
    // 多维数组 每项为一行数据
    var arr_row = [];
    // 大小偏移数据
    var arr_msg = [];
    // 每行数据长度
    var ui_max_cnt = 1;
    // 补充数据位置
    var arr_supply = [];

    for (var idx = 0; idx < arr_mod.length; idx++) {
        var obj_item = arr_mod[idx];
        var obj_item_msg = mc_get_child_pot_size(obj_item[0]);
        var arr_pot = obj_item_msg.str_pot.split(",");
        var arr_size = obj_item_msg.str_size.split("X");
        var ui_top = arr_pot[1] - ui_base_top;
        var ui_row_num = Math.floor(ui_top / ui_base_h);
        var obj_msg = new mc_box_msg_format();

        obj_msg.left = Number(arr_pot[0]);
        obj_msg.top = arr_pot[1];
        obj_msg.width = arr_size[0];
        obj_msg.height = arr_size[1];

        if (arr_row[ui_row_num]) {
            arr_msg[ui_row_num].push(obj_msg);
            arr_row[ui_row_num].push(obj_item);
            arr_supply[ui_row_num][obj_msg.left] = true;
            if (ui_max_cnt < arr_row[ui_row_num].length) {
                ui_max_cnt = arr_row[ui_row_num].length;
            }
        } else {
            arr_msg[ui_row_num] = [obj_msg];
            arr_row[ui_row_num] = [obj_item];
            arr_supply[ui_row_num] = {};
            arr_supply[ui_row_num][obj_msg.left] = true;
        }
    }

    // 过滤空项
    arr_row = mc_filter_tool(function (item) {
        return "[object Undefined]" !== Object.prototype.toString.call(item);
    }, arr_row);
    arr_msg = mc_filter_tool(function (item) {
        return "[object Undefined]" !== Object.prototype.toString.call(item);
    }, arr_msg);

    // 获取补充数据位置及数组
    var obj_supply_pot = {};
    var arr_supply_pot = [];

    if (b_supply) {
        var ui_supply_len = 0;

        // 获取最长
        for (var idx_supply = 0; idx_supply < arr_supply.length; idx_supply++) {
            var arr_key = Object.keys(arr_supply[idx_supply]);

            if (ui_supply_len < arr_key.length) {
                ui_supply_len = arr_key.length;
                arr_supply_pot = arr_key;
            }
        }
        for (var index_supply = 0; index_supply < arr_supply_pot.length; index_supply++) {
            obj_supply_pot[arr_supply_pot[index_supply]] = index_supply;
        }
        arr_row = mc_supply_sort_data(arr_row, arr_msg, arr_supply_pot, obj_supply_pot, "left") || arr_row;
    } else {
        // 对比合并
        // for (var idx_row = 0; idx_row < arr_row.length - 1; idx_row++) {
        //     var ui_len = arr_row[idx_row].length;

        //     if (ui_len < ui_max_cnt) {
        //         var obj_prew_row_msg = arr_msg[idx_row][0];

        //         // if (Number(obj_prew_row_msg.left) + Number(obj_prew_row_msg.height) > Number(arr_msg[idx_row + 1][0][0].top)) {
        //         if (Number(obj_prew_row_msg.left) + Number(obj_prew_row_msg.height) > Number(arr_msg[idx_row + 1][0].top)) {
        //             arr_row.splice(idx_row, idx_row + 1, arr_row[idx_row].concat(arr_row[idx_row + 1]));
        //             arr_msg.splice(idx_row, idx_row + 1, arr_msg[idx_row].concat(arr_msg[idx_row + 1]));
        //         }
        //     }
        // }
        sort_data();
    }


    return arr_row;

    function sort_data() {
        // 排序每行left 由小到大
        for (var idx_sort = 0; idx_sort < arr_row.length; idx_sort++) {
            var ary_row = arr_row[idx_sort];
            var ary_msg = arr_msg[idx_sort];

            for (var idx_data = 1; idx_data < ary_row.length; idx_data++) {
                if (!ary_row[idx_data]) {
                    continue;
                }
                var o_data = ary_row[idx_data][0];
                var o_msg = ary_msg[idx_data];

                if (Number(o_msg.left) < Number(ary_msg[idx_data - 1].left)) {
                    // if (Number(o_msg.left) < Number(ary_msg[idx_data - 1].left) && Number(o_msg.top) <= Number(ary_msg[idx_data - 1].top)) {
                    var ui_index = idx_data - 1;

                    while (Number(o_msg.left) < Number(ary_msg[ui_index].left)) {
                        // while (Number(o_msg.left) < Number(ary_msg[ui_index].left) && Number(o_msg.top) <= Number(ary_msg[idx_data - 1].top)) {
                        ary_row[ui_index + 1] = ary_row[ui_index];
                        ui_index--;
                        if (0 > ui_index) {
                            break;
                        }
                    }
                    ary_row[ui_index + 1] = $(o_data);
                }
            }
        }
    }
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取垂直排列数据
 * 参数:
 *     @param {Promise<Array>} arr_mod 当前选中元素
 *     @param {Promise<Array>} b_supply 布局连线时补充数据true 可为空
 * 返回：
 *     @returns {Promise<Boolean>}
 *      false 参数错误
 *      arr_row 多维数组 每项为一列数据 每列元素从上到下排列
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.21
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_quick_connect_col_data(arr_mod, b_supply) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_mod) || 0 === arr_mod.length) {
        return false;
    }
    var obj_base_msg = mc_get_child_pot_size(arr_mod[0][0]);
    var ui_base_left = Number(obj_base_msg.str_pot.split(",")[0]);
    var ui_base_w = Number(obj_base_msg.str_size.split("X")[0]);
    // 多维数组 每项为一行数据
    var arr_col = [];
    var arr_msg = [];
    // 每行数据长度
    var ui_max_cnt = 1;
    var arr_supply = [];
    var arr_negative = [];
    var arr_negative_msg = [];

    for (var idx = 0; idx < arr_mod.length; idx++) {
        var obj_item = arr_mod[idx];
        var obj_item_msg = mc_get_child_pot_size(obj_item[0]);
        var arr_pot = obj_item_msg.str_pot.split(",");
        var arr_size = obj_item_msg.str_size.split("X");
        var ui_top = Number(arr_pot[0]) - ui_base_left;
        var ui_row_num = Math.floor(ui_top / ui_base_w);
        var obj_msg = new mc_box_msg_format();
        var ui_negative = 0;

        obj_msg.left = Number(arr_pot[0]);
        obj_msg.top = arr_pot[1];
        obj_msg.width = arr_size[0];
        obj_msg.height = arr_size[1];

        // 处理负数情况
        if (0 > ui_row_num) {
            ui_negative = Math.abs(ui_row_num);
            if (arr_negative[ui_negative]) {
                arr_negative_msg[ui_negative].push(obj_msg);
                arr_negative[ui_negative].push(obj_item);
            } else {
                arr_negative[ui_negative] = [obj_item];
                arr_negative_msg[ui_negative] = [obj_msg];
            }
        }
        if (arr_col[ui_row_num]) {
            arr_msg[ui_row_num].push(obj_msg);
            arr_col[ui_row_num].push(obj_item);
            arr_supply[ui_row_num][obj_msg.top] = true;

            if (ui_max_cnt < arr_col[ui_row_num].length) {
                ui_max_cnt = arr_col[ui_row_num].length;
            }
        } else {
            arr_msg[ui_row_num] = [obj_msg];
            arr_col[ui_row_num] = [obj_item];
            arr_supply[ui_row_num] = {};
            arr_supply[ui_row_num][obj_msg.top] = true;
        }
    }

    if (0 !== arr_negative.length && 0 !== arr_negative_msg.length) {
        arr_negative = mc_filter_tool(function (item) {
            return "[object Undefined]" !== Object.prototype.toString.call(item);
        }, arr_negative);
        arr_negative = arr_negative.reverse();

        arr_negative_msg = mc_filter_tool(function (item) {
            return "[object Undefined]" !== Object.prototype.toString.call(item);
        }, arr_negative_msg);

        arr_negative_msg = arr_negative_msg.reverse();
        arr_col = arr_negative.concat(arr_col);
        arr_msg = arr_negative_msg.concat(arr_msg);
    }

    // 过滤空项
    arr_col = mc_filter_tool(function (item) {
        return "[object Undefined]" !== Object.prototype.toString.call(item);
    }, arr_col);
    arr_msg = mc_filter_tool(function (item) {
        return "[object Undefined]" !== Object.prototype.toString.call(item);
    }, arr_msg);

    var obj_supply_pot = {};
    var arr_supply_pot = [];

    if (b_supply) {
        var ui_supply_len = 0;

        // 获取最长
        for (var idx_supply = 0; idx_supply < arr_supply.length; idx_supply++) {
            var arr_key = Object.keys(arr_supply[idx_supply]);

            if (ui_supply_len < arr_key.length) {
                ui_supply_len = arr_key.length;
                arr_supply_pot = arr_key;
            }
        }
        for (var index_supply = 0; index_supply < arr_supply_pot.length; index_supply++) {
            obj_supply_pot[arr_supply_pot[index_supply]] = index_supply;
        }
        arr_col = mc_supply_sort_data(arr_col, arr_msg, arr_supply_pot, obj_supply_pot, "top") || arr_col;
    } else {
        // 对比合并
        // for (var idx_row = 0; idx_row < arr_col.length - 1; idx_row++) {
        //     var ui_len = arr_col[idx_row].length;

        //     if (ui_len < ui_max_cnt) {
        //         var obj_prew_row_msg = arr_msg[idx_row][0];

        //         // if (obj_prev_row_item.offsetLeft + obj_prev_row_item.offsetWidth > arr_col[idx_row + 1][0][0].offsetLeft) {
        //         if (Number(obj_prew_row_msg.left) + Number(obj_prew_row_msg.width) > Number(arr_col[idx_row + 1][0].left)) {
        //             arr_col.splice(idx_row, idx_row + 1, arr_col[idx_row].concat(arr_col[idx_row + 1]));
        //             arr_msg.splice(idx_row, idx_row + 1, arr_msg[idx_row].concat(arr_msg[idx_row + 1]));
        //         }
        //     }
        // }
        sort_data();
    }


    function sort_data() {
        // 排序每行top 由小到大
        for (var idx_sort = 0; idx_sort < arr_col.length; idx_sort++) {
            var ary_row = arr_col[idx_sort];
            var ary_msg = arr_msg[idx_sort];

            for (var idx_data = 1; idx_data < ary_row.length; idx_data++) {
                if (!ary_row[idx_data]) {
                    continue;
                }
                var o_data = ary_row[idx_data][0];
                var o_msg = ary_msg[idx_data];

                if (Number(o_msg.top) < Number(ary_msg[idx_data - 1].top)) {
                    // if (Number(o_msg.top) < Number(ary_row[idx_data - 1].top) && Number(o_msg.left) <= Number(ary_msg[idx_data - 1].left)) {
                    var ui_index = idx_data - 1;

                    while (Number(o_msg.top) < Number(ary_msg[ui_index].top)) {
                        // while (Number(o_msg.top) < Number(ary_row[ui_index].top) && Number(o_msg.left) <= Number(ary_msg[idx_data - 1].left)) {
                        ary_row[ui_index + 1] = ary_row[ui_index];
                        ui_index--;
                        if (0 > ui_index) {
                            break;
                        }
                    }
                    ary_row[ui_index + 1] = $(o_data);
                }
            }
        }
    }

    return arr_col;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    构造快速布局矩阵数据  空项为字符串
 * 参数:
 *     @param {Promise<Array>} arr_rowcol 行/列数据
 *     @param {Promise<Array>} arr_msg 行/列元素信息
 *     @param {Promise<Array>} arr_supply_pot 每行/列数据位置数组
 *     @param {Promise<Object>} obj_supply_pot 每行/列数据位置下标
 *     @param {Promise<String>} str_type 获取类型 top获取垂直数据/left水平数据
 * 返回：
 *     @returns {Promise<Boolean>}
 *      false 参数错误
 *      arr_result 多维数组 每项为一列/行数据 每列元素从上到下排列/每行元素从左到右排列
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.24
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_supply_sort_data(arr_rowcol, arr_msg, arr_supply_pot, obj_supply_pot, str_type) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_rowcol) || 0 === arr_rowcol.length) {
        return false;
    }
    if ("[object Array]" !== Object.prototype.toString.call(arr_msg) || 0 === arr_msg.length) {
        return false;
    }
    if ("[object Array]" !== Object.prototype.toString.call(arr_supply_pot) || 0 === arr_supply_pot.length) {
        return false;
    }
    if ("[object Object]" !== Object.prototype.toString.call(obj_supply_pot) || 0 === obj_supply_pot.length) {
        return false;
    }
    if ("[object String]" !== Object.prototype.toString.call(str_type) || 0 === str_type.length) {
        return false;
    }
    var arr_result = [];

    for (var idx_sort = 0; idx_sort < arr_rowcol.length; idx_sort++) {
        var ary_row = arr_rowcol[idx_sort];
        var ary_msg = arr_msg[idx_sort];
        var arr_supply_copy = $.extend(true, [], arr_supply_pot);

        arr_result.push(arr_supply_copy);

        for (var idx_data = 0; idx_data < ary_row.length; idx_data++) {
            var o_data = ary_row[idx_data][0];
            var o_msg = ary_msg[idx_data];
            var ui_idx = obj_supply_pot[o_msg[str_type]];

            arr_result[idx_sort][ui_idx] = $(o_data);
        }
    }
    return arr_result;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    存储大小偏移数据格式
 * 参数:
 *     无
 * 返回：
 *     NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.21
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_box_msg_format() {
    this.left = 0;
    this.top = 0;
    this.height = 0;
    this.width = 0;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    构造快速连线指定方向数据数组
 * 参数:
 *     @param {Promise<Array>} arr_mod 当前选中元素
 *     @param {Promise<String>} str_dtc 数据排列方向 horz/vert_even/odd_reverse/null 水平/垂直排列_偶数排/奇数排反向_是否整体反向
 * 返回：
 *     @returns {Promise<Boolean>}
 *      false 参数错误
 *      arr_result 排列完成数组
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.21
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_quick_connect_dct_data(arr_mod, str_dtc) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_mod) || 0 === arr_mod.length) {
        return false;
    }
    if ("string" !== typeof str_dtc || 0 === str_dtc.length) {
        return false;
    }
    var arr_type = str_dtc.split("_");
    var ui_reverse = -1;
    var arr_arrow = [];
    var arr_result = [];

    // 排列方向
    if ("horz" === arr_type[0]) {
        arr_mod = mc_get_quick_connect_row_data(arr_mod);
    }
    if ("vert" === arr_type[0]) {
        arr_mod = mc_get_quick_connect_col_data(arr_mod);
    }

    // 奇/偶排反向
    if ("even" === arr_type[1]) {
        ui_reverse = 1;
    }
    if ("odd" === arr_type[1]) {
        ui_reverse = 0;
    }
    // 特殊情况处理
    if (1 === arr_mod.length % 2) {
        if ("horz_odd_reverse" === str_dtc || "vert_odd_reverse" === str_dtc) {
            ui_reverse = 1;
        }
        if ("horz_even_reverse" === str_dtc || "vert_even_reverse" === str_dtc) {
            ui_reverse = 0;
        }
    }

    for (var idx = 0; idx < arr_mod.length; idx++) {
        if (ui_reverse === idx % 2) {
            arr_mod[idx] = select_one_reverse(arr_mod[idx]);
        }
        if ("reverse" === arr_type[2]) {
            // 反向填充数据
            arr_arrow.unshift(arr_mod[idx]);
        } else {
            arr_arrow.push(arr_mod[idx]);
        }
    }
    // 合并
    for (var idx_concat = 0; idx_concat < arr_arrow.length; idx_concat++) {
        arr_result = arr_result.concat(arr_arrow[idx_concat]);
    }
    return arr_result;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    构造快速连线图示
 * 参数:
 *     @param {Promise<Object>} o_parent 父元素
 *     @param {Promise<Array>} arr_icon icon图标数组
 * 返回：
 *     @returns {Promise<Boolean>}
 *      false 参数错误
 *      true 构造成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.21
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_construct_quick_connect_img(o_parent, arr_icon) {
    if ("object" !== typeof o_parent || 0 === o_parent.length) {
        return false;
    }
    if (!(Array.isArray(arr_icon)) || 0 === arr_icon.length) {
        return false;
    }
    var arr_dct = ["horz_even", "horz_odd_reverse", "horz_odd", "horz_even_reverse", "vert_even", "vert_odd", "vert_odd_reverse", "vert_even_reverse"];

    o_parent.innerHTML = "";
    for (var idx_icon = 0; idx_icon < arr_icon.length; idx_icon++) {
        var o_div = document.createElement("div");

        o_div.id = arr_dct[idx_icon];
        o_div.className = arr_icon[idx_icon];
        o_parent.appendChild(o_div);
    }
    return true;
}

// 对开
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    快速连线设置对开控件，对应json字串
 * 参数:
 *     无
 * 返回：
 *     @returns {Promise<String>}
 *      对应json字串
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.11.24
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_split_construct() {
    var obj_sdk_param = new mc_sdk_param();
    var str_param_name = "";
    var str_param_value = "";

    obj_sdk_param.set_param_clear();
    str_param_name = "MC_LANG_CASCADE_SYSTEM";
    str_param_value = "0";
    obj_sdk_param.set_param_value(str_param_name, str_param_value);
    obj_sdk_param.set_attr_val(str_param_name, "UI_TYPE", "OPTION");
    obj_sdk_param.set_attr_val(str_param_name, "ARRAY", "0=MC_LANG_OPTION_LEFT_TO_RIGHT,1=MC_LANG_OPTION_RIGHT_TO_LEFT,2=MC_LANG_OPTION_TOP_TO_BOTTOM,3=MC_LANG_OPTION_BOTTOM_TO_TOP");

    str_param_name = "MC_LANG_OUTPUT_MODE";
    str_param_value = "1";
    obj_sdk_param.set_param_value(str_param_name, str_param_value);
    obj_sdk_param.set_attr_val(str_param_name, "UI_TYPE", "OPTION");
    obj_sdk_param.set_attr_val(str_param_name, "ARRAY", "0=MC_LANG_OPTION_NOT_SPLIT,1=MC_LANG_OPTION_TWO_SPLIT,2=MC_LANG_OPTION_THREE_SPLIT,3=MC_LANG_OPTION_FOUR_SPLIT");

    str_param_name = "MC_LANG_PLUG_THE_ORDER";
    str_param_value = "0";
    obj_sdk_param.set_param_value(str_param_name, str_param_value);
    obj_sdk_param.set_attr_val(str_param_name, "UI_TYPE", "OPTION");
    obj_sdk_param.set_attr_val(str_param_name, "ARRAY", "0=MC_LANG_OPTION_POSITIVE_SEQUENCE,1=MC_LANG_OPTION_INVERTED_ORDER");

    return obj_sdk_param.get_json();
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    箱体连接快速连线设置hub jx 、开启对开开关控件json字串
 * 参数:
 *     无
 * 返回：
 *     @returns {Promise<String>}
 *      对应json字串
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.11.24
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_split_switch_construct() {
    var obj_sdk_param = new mc_sdk_param();

    obj_sdk_param.set_param_clear();
    var str_param_name = "MC_LANG_SPLIT";
    var str_jx_unit = "J";

    obj_sdk_param.set_param_value(str_jx_unit, "1");
    obj_sdk_param.set_attr_val(str_jx_unit, "UI_TYPE", "STEP_EDIT");
    obj_sdk_param.set_attr_val(str_jx_unit, "VAL_TYPE", "uint");
    obj_sdk_param.set_attr_val(str_jx_unit, "MIN_VAL", "1");
    obj_sdk_param.set_attr_val(str_jx_unit, "STEP", "1");

    obj_sdk_param.set_param_value(str_param_name, "1");
    obj_sdk_param.set_attr_val(str_param_name, "UI_TYPE", "TOGGLE");
    obj_sdk_param.set_attr_val(str_param_name, "SWITCH_TEXT", "YES,NO");
    return obj_sdk_param.get_json();
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    大屏连接快速连线控件子窗添加对开开关
 * 参数:
 *     @param {Promise<String>} str_json 快速连线字串
 * 返回：
 *     @returns {Promise<String>}
 *      对应json字串
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.11.24
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_screen_add_split_html(str_json) {
    if ("string" !== typeof str_json || 0 === str_json.length) {
        return false;
    }
    var obj_sdk_param = new mc_sdk_param();
    var str_param_name = "MC_LANG_SPLIT";

    obj_sdk_param.set_param_clear();
    obj_sdk_param.set_json(str_json);
    obj_sdk_param.set_param_value(str_param_name, "0");
    obj_sdk_param.set_attr_val(str_param_name, "UI_TYPE", "TOGGLE");
    obj_sdk_param.set_attr_val(str_param_name, "SWITCH_TEXT", "YES,NO");
    return obj_sdk_param.get_json();
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    快速连线 对开连线应用
 * 参数:
 *     @param {Promise<Object>} obj_apply_data 控件参数对象
 *     @param {Promise<Array>} arr_mod 设置模块jq数组
 *     @param {Promise<Number>} ui_hub_num 起始对开下标 如J1或P1 === 1
 *     @param {Promise<String>} str_card_name 大屏连接 卡name 如S0:
 *     @param {Promise<Object>} obj_same_hub_queue 连线数据队列
 * 返回：
 *     @returns {Promise<Object>}
 *      false 参数错误
 *      obj_same_hub_queue 最新连线队列
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.11.24
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_quick_connect_split(obj_apply_data, arr_mod, ui_hub_num, str_card_name, obj_same_hub_queue) {
    if ("object" !== typeof obj_apply_data) {
        return false;
    }
    if ("[object Array]" !== Object.prototype.toString.call(arr_mod) || 0 === arr_mod.length) {
        return false;
    }
    var init_hub_name = ui_hub_num;
    // 取值；级联方向，输出方式，插头顺序；
    var mod_cascade_dir = obj_apply_data.MC_LANG_CASCADE_SYSTEM.val;
    var mod_output_mode = obj_apply_data.MC_LANG_OUTPUT_MODE.val;
    var mod_order = obj_apply_data.MC_LANG_PLUG_THE_ORDER.val;

    // 级联方式设置 ------
    // 设置为y轴级联方向
    if ("2" === mod_cascade_dir || "3" === mod_cascade_dir) {
        // 获取垂直排列数据
        arr_mod = mc_get_quick_connect_col_data(arr_mod, true);
        // axis_dir = 1;
    } else {
        // 水平排列数据
        arr_mod = mc_get_quick_connect_row_data(arr_mod, true);
    }
    // 输出方式设置 ------
    // 每组数据数
    var ui_mode_num = Number(mod_output_mode) + 1;
    // 求余
    var mode_rem = arr_mod[0].length % ui_mode_num;
    // 对开方式的一组个数(有对开情况下相同jx值为一组，mode_gp_num 示该组jx值有多少个模组)
    var mode_gp_num = Math.floor(arr_mod[0].length / ui_mode_num);
    // 定义对开排列数组 每组数据个数；
    var arr_output_sort = new Array(ui_mode_num);

    for (var idx = 0; idx < arr_output_sort.length; idx++) {
        arr_output_sort[idx] = mode_gp_num;
        if (0 !== mode_rem) {
            arr_output_sort[idx] = mode_gp_num + 1;
            mode_rem--;
        }
    }

    // 插头顺序设置 -------
    if ("1" === mod_order) {
        // 数据外层反向
        arr_mod = arr_mod.reverse();
    }

    if ("1" === mod_cascade_dir || "3" === mod_cascade_dir) {
        // 内层反向
        for (var item = 0; item < arr_mod.length; item++) {
            arr_mod[item] = arr_mod[item].reverse();
        }
    }
    // 构造连线数据 -------
    var str_hub_name = "J";

    if (str_card_name) {
        // 大屏
        str_hub_name = "P";
    }
    var u_index = 0;

    var arr_pot = mc_get_split_pot(arr_output_sort);

    // 列从左到右 [3,3,2]
    for (var i = 0; i < arr_output_sort.length; i++) {
        // 3
        var ui_num = arr_output_sort[i];
        var ui_index = ui_hub_num;

        if (i) {
            // ui_index = arr_mod.length * i + 1;
            ui_index = arr_mod.length * i + init_hub_name;
        }

        for (var j = 0; j < ui_num; j++) {
            var ui_push = arr_pot[u_index];

            // 相同line数据
            ui_hub_num = ui_index;
            for (var index = 0; index < arr_mod.length; index++) {
                // 每行数据
                var arr_item = arr_mod[index];
                var obj_target = arr_item[ui_push];

                if (!obj_target) {
                    continue;
                }
                // 补充数据
                if ("string" === typeof obj_target) {
                    ui_hub_num++;
                    continue;
                }
                var obj_center_text = obj_target.children(".mod_hub_box").children(".mod_hub_div");
                var obj_card_name = mc_get_appoint_obj(obj_target, "card_idx", true);
                var str_txt = str_hub_name + ui_hub_num;
                var str_key = (str_card_name + str_txt).trim();
                var s_card_name = "";

                if (str_card_name) {
                    s_card_name = obj_card_name.text() + ":";
                    obj_card_name.text(str_card_name.substring(0, str_card_name.lastIndexOf(":")));
                }
                var str_new_class_name = str_recvcard_class_name_prefix + "_" + str_key.replace(/:/g, "_");

                var ui_bgc_css = str_key.match(/\d+/g).reduce(function (total, currentValue) {
                    return Number(total) + Number(currentValue);
                });


                mc_add_css_rules("theme_hl_layout", "." + str_new_class_name, get_bgc_css(ui_bgc_css));
                change_block_bgc(obj_target, str_new_class_name);
                // 删除原先队列数据
                delete_mod_queue(s_card_name + obj_center_text.text(), obj_target);
                add_hub_queue(str_key, obj_target);
                // if (obj_same_hub_queue[str_key]) {
                //     obj_same_hub_queue[str_key].push(obj_target);
                // } else {
                //     obj_same_hub_queue[str_key] = [obj_target];
                // }

                // 去除未连线标识
                mc_remove_unset_tip(obj_target);
                obj_center_text.text(str_txt);
                ui_hub_num++;
            }
            u_index++;
        }
    }
    return obj_same_hub_queue;

    // 连线队列添加操作
    function add_hub_queue(s_key, o_target) {
        if (obj_same_hub_queue[s_key]) {
            obj_same_hub_queue[s_key].push(o_target);
        } else {
            obj_same_hub_queue[s_key] = [o_target];
        }
    }
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取对开添加模块顺序数组
 * 参数:
 *     @param {Promise<Array>} arr_output_sort 每项为对开每组个数
 * 返回：
 *     @returns {Promise<Array>}
 *      false 参数错误
 *      arr_result 顺序下标数组
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.11.24
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_split_pot(arr_output_sort) {
    if (!(Array.isArray(arr_output_sort)) || 0 === arr_output_sort.length) {
        return false;
    }
    var arr_result = [];
    var ui_sort = 0;
    var arr_index = [];

    for (var add = 0; add < arr_output_sort.length; add++) {
        var ui_add = arr_output_sort[add];

        for (var j = 0; j < ui_add; j++) {
            arr_index.push(ui_sort);
            ui_sort++;
        }

        if (1 === add % 2) {
            arr_index = arr_index.reverse();
        }
        arr_result = arr_result.concat(arr_index);
        arr_index = [];
    }
    return arr_result;
}


// -------------------------------------------请求------------------------------------------------
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    发送/固化 接收卡偏移信息  固化时同时发送巡检信息
 *    开启重置时 发送主控、分控图像信息、输出端口图形信息
 * 参数:
 *     @param {Promise<Array>} ary_data 计算后数据
 *     @param {Promise<Boolean>} b_load 是否固化
 *     @param {Promise<Object>} obj_pot 参数对象
 *     @param {Promise<function>} fun_callback 回调
 * 返回：
 *     @returns {Promise<Array>}
 *      false 参数有误
 *      true 删除完成
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.12
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_screen_send(ary_data, b_load, obj_pot, fun_callback) {
    var obj_recvcard_data = mc_recvcard_req_data(ary_data, obj_pot.recvcard);
    // 发送卡HUB卡输出端口数据
    var arr_sendcard_port = mc_req_img_str(mc_recvcard_req_data(ary_data, obj_pot.sendport));
    var arr_hubcard_port = mc_req_img_str(mc_recvcard_req_data(ary_data, obj_pot.hubport));
    var arr_key = Object.keys(obj_recvcard_data);
    var str_success_tip = "";
    var str_fail_tip = "";
    var str_code = "";
    var str_error_code = g_obj_lang.get_item_val("MC_LANG_POPOUT_ERROR_CODE");
    // 输出端口设置提示
    var str_sendport_tip = g_obj_lang.get_item_val("MC_LANG_POPOUT_SENDCARD_PORT_SET_FAIL");
    var str_hubport_tip = g_obj_lang.get_item_val("MC_LANG_POPOUT_HUBCARD_PORT_SET_FAIL");
    // 内部错误提示
    var str_internal_error = g_obj_lang.get_item_val("MC_LANG_POPOUT_INTERNAL_ERROR");
    var str_sendoffset_tip = "";
    var str_sendoffset_tip_cnt = g_obj_lang.get_item_val("MC_LANG_SURRENT");
    var str_sendoffset_tip_total = g_obj_lang.get_item_val("MC_LANG_TOTAL_QUANTITY");

    if (0 === arr_key.length) {
        str_code += "<div>" + g_obj_lang.get_item_val("MC_LANG_BOX_OFFSET_INFORMATION") + "</div>";
    }
    if (b_load) {
        // 固化
        str_success_tip = g_obj_lang.get_item_val("MC_LANG_LOAD_SUCCESS");
        str_fail_tip = g_obj_lang.get_item_val("MC_LANG_POPOUT_RECVCARD_OFFSETIMG_LOADFAIL");
        str_sendoffset_tip = g_obj_lang.get_item_val("MC_LANG_LOAD_BOXOFFSET");
    } else {
        // 发送
        str_success_tip = g_obj_lang.get_item_val("MC_LANG_SNED_SUCCESS");
        str_fail_tip = g_obj_lang.get_item_val("MC_LANG_POPOUT_RECVCARD_OFFSETIMG_SENDFAIL");
        str_sendoffset_tip = g_obj_lang.get_item_val("MC_LANG_SEND_BOXOFFSET");
    }
    if (!b_hubcard_getname_success && 0 === arr_hubcard_port.length) {
        str_code += "<div>HUB," + str_internal_error + "</div>";
    }
    // 请求参数
    var ary_box_offset = [];
    var ui_port_len = 0;
    var ary_cards = [];
    var aty_cardport_func = [];
    var ary_card_func = [];
    var ary_cardport = [];

    if (parent.b_if_reset_port) {
        aty_cardport_func = ["HW_SENDCARD_OUTPORT_IMG_RECT", "HW_HUBCARD_OUTPORT_IMG_RECT"];
        ary_card_func = ["HW_SENDCARD_IMG_RECT", "HW_HUBCARD_IMG_RECT"];
        ary_cardport = [get_card_port_reqdata(arr_sendcard_port, false), get_card_port_reqdata(arr_hubcard_port, true)];
        var arr_hubport_param = obj_pot.hubport;
        var ary_hubcard = mc_recvcard_req_data(ary_data, arr_hubport_param, true);
        var arr_sendcard = [];
        var arr_hubcard = [];

        for (var indexsend = 0; indexsend < obj_pot.sendport.length; indexsend++) {
            var obj_item = ary_data[indexsend];

            if (obj_item) {
                arr_sendcard.push({
                    PARAM: String(indexsend),
                    STR_IMG: "(" + obj_item.X + ":" + obj_item.Y + ":" + obj_item.W + ":" + obj_item.H + ")"
                });
            }
        }
        for (var indexhub = 0; indexhub < ary_hubcard.length; indexhub++) {
            var obj_hub_item = ary_hubcard[indexhub];

            if (obj_hub_item) {
                arr_hubcard.push({
                    PARAM: arr_hubport_param[indexhub],
                    STR_IMG: "(" + obj_hub_item.X + ":" + obj_hub_item.Y + ":" + obj_hub_item.W + ":" + obj_hub_item.H + ")"
                });
            }
        }
        ui_port_len = ary_cardport.length;
        ary_cards = [arr_sendcard, arr_hubcard];
    }

    var obj_nega_os = {};
    // 负偏移需修改偏移值

    if (!parent.G_B_NEGA_OFFSET) {
        obj_nega_os = mc_handle_nega_offset(obj_same_hub_queue);
    }

    for (var idx_req = 0; idx_req < arr_key.length; idx_req++) {
        var str_param = arr_key[idx_req];
        var arr_data = obj_recvcard_data[str_param];
        var index = 0;

        while (index < arr_data.length) {
            var obj_req = new format_req_param();
            var obj_data = arr_data[index];

            obj_req.str_idx = "(" + str_param + ":" + index + ")";
            obj_req.str_chtrlchip_name = obj_data.CHIP_NAME;
            if (parent.G_B_NEGA_OFFSET) {
                obj_req.str_offset_msg = "(0:0:" + obj_data.X + ":" + obj_data.Y + ")";
            } else {
                var obj_cut = obj_nega_os[obj_req.str_idx];
                var left = Number(obj_data.X) - obj_cut.left;
                var top = Number(obj_data.Y) - obj_cut.top;

                obj_req.str_offset_msg = "(0:0:" + left + ":" + top + ")";
            }
            obj_req.str_autocheck_msg = "(" + obj_data.X + ":" + obj_data.Y + ":" + obj_data.W + ":" + obj_data.H + ")";
            ary_box_offset.push(obj_req);
            index++;
        }
    }

    function mc_handle_nega_offset(obj) {
        var obj_return = {};

        for (var key in obj) {
            if (Object.hasOwnProperty.call(obj, key)) {
                var arr = obj[key];
                var arr_len = arr.length;

                if (0 === arr_len) {
                    continue;
                }

                for (var idx = 0; idx < arr_len; idx++) {
                    var str_order = "";
                    var arr_each_order = [];

                    var str_s = "0";
                    var str_s_p = "0";
                    var str_h = "0";
                    var str_h_p = "0";

                    if (-1 !== key.indexOf("_")) {
                        // 有分控
                        arr_each_order = key.split(":");
                        var arr_hub_order = arr_each_order[0].split("_");

                        str_s = Number(arr_hub_order[0].slice(1)) - 1;
                        str_s_p = Number(arr_hub_order[1].slice(1)) - 1;
                        str_h = Number(arr_hub_order[2].slice(1)) - 1;
                        str_h_p = Number(arr_each_order[1].slice(1)) - 1;
                    } else {
                        arr_each_order = key.split(":");
                        str_s = Number(arr_each_order[0].slice(1)) - 1;
                        str_s_p = Number(arr_each_order[1].slice(1)) - 1;
                    }
                    str_order = "(" + str_s + ":" + str_s_p + ":" + str_h + ":" + str_h_p + ":" + idx + ")";

                    // 获取裁剪变换
                    var dom = arr[idx][0];
                    var str_cut = dom.getAttribute("transform_msg");

                    var obj_each_cut = {
                        left: 0,
                        right: 0,
                        top: 0,
                        bottom: 0
                    };

                    if (!str_cut) {
                        obj_return[str_order] = obj_each_cut;
                        continue;
                    }

                    var arr_cut = str_cut.split("_")[4].split(",");

                    obj_each_cut = {
                        left: Number(arr_cut[0]) ? Number(arr_cut[0]) : 0,
                        right: Number(arr_cut[1]) ? Number(arr_cut[1]) : 0,
                        top: Number(arr_cut[2]) ? Number(arr_cut[2]) : 0,
                        bottom: Number(arr_cut[3]) ? Number(arr_cut[3]) : 0
                    };

                    obj_return[str_order] = obj_each_cut;
                }
            }
        }

        return obj_return;
    }

    dg_send_recvcard_offset(0, ary_box_offset.length);
    function dg_send_recvcard_offset(ui_idx, ui_total) {
        if (ui_idx < ui_total) {
            mc_get_top_fun("mc_update_load_txt", str_sendoffset_tip + str_sendoffset_tip_cnt + (ui_idx + 1) + "，" + str_sendoffset_tip_total + ui_total, "mc_screen_loading_text");
            var o_data = ary_box_offset[ui_idx];
            var str_param_key = o_data.str_idx;
            var str_chip_name = o_data.str_chtrlchip_name;
            // 工作模式参数
            var str_workmode = mc_get_req_workmode_data(b_load);

            // 写入箱体偏移信息
            mc_set_box_offset(str_param_key, o_data.str_offset_msg, str_chip_name, function (str_code_req) {
                if ("0x00000000" !== str_code_req && str_code_req) {
                    str_code += "<div>" + str_param_key + "," + str_fail_tip + ";" + str_error_code + ":" + str_code_req + "</div>";
                }
                dg_send_recvcard_offset(++ui_idx, ui_total);
            }, b_load, str_workmode);
        } else {
            // if (b_load) {
            //     // 固化时 写入巡检信息
            //     mc_req_sendcard_autochecks(ary_box_offset, function (str_check) {
            //         if ("0x00000000" !== str_check && str_check) {
            //             str_code += "<div>写入巡检信息," + str_check_tip + ";" + str_error_code + ":" + str_check + "</div>";
            //         }
            //         send_cardport_img(0, ui_port_len);
            //     }, b_load);
            // } else {
            if (ui_port_len) {
                mc_get_top_fun("mc_update_load_txt", g_obj_lang.get_item_val("MC_LANG_SEND_MAIN_CONTROL_AND_SUB_CONTROL_IMGMSG"), "mc_screen_loading_text");
            }
            send_cardport_img(0, ui_port_len);
            // }
        }
    }

    // 写入sendcard/hubcard输出端口图像偏移信息
    function send_cardport_img(ui_idx, ui_total) {
        if (ui_idx < ui_total) {
            var s_tip = "";

            if (0 === ary_cardport[ui_idx].length) {
                send_cardport_img(++ui_idx, ui_total);
                return;
            }
            if (0 === ui_idx) {
                s_tip = str_sendport_tip;
            } else {
                s_tip = str_hubport_tip;
            }
            mc_set_cardport_img_rect(aty_cardport_func[ui_idx], ary_cardport[ui_idx], function (s_code) {
                if ("0x00000000" !== s_code && s_code) {
                    str_code += "<div>" + s_tip + ";" + str_error_code + ":" + s_code + "</div>";
                }
                send_cardport_img(++ui_idx, ui_total);
            }, b_load);
        } else {
            send_card_img(0, ui_total, ary_card_func.length);
            return;
        }
    }

    function send_card_img(ui_idx, ui_total) {
        if (ui_idx < ui_total) {
            if (0 === ary_cards[ui_idx].length) {
                send_card_img(++ui_idx, ui_total);
                return;
            }
            mc_set_cards_img_rect(ary_card_func[ui_idx], ary_cards[ui_idx], function () {
                send_card_img(++ui_idx, ui_total);
            }, b_load);
        } else {
            // 请求结束
            if (0 === str_code.length) {
                fun_callback(str_success_tip);
            } else {
                fun_callback(str_code);
            }
            return;
        }
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    发送SNEDCARD/HUBCARD输出端口图像偏移信息
 * 参数:
 *    @param { Promise<String> } str_fun func
 *    @param { Promise<Array> } arr_param 请求参数数组对象
 *    @param { Promise<Function> } fun_callback 回调函数
 *    @param { Promise<Boolean> } b_load 是否固化
 * 备注:
 * 参数 arr_param ={
 *     str_idx:"索引",
 *     str_offset_msg:"偏移信息",
 *     str_autocheck_msg:"巡检信息",
 *     str_chtrlchip_name:"芯片信息",
 *     }
 * 返回：
 *    NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.28
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_set_cardport_img_rect(str_fun, arr_param, fun_callback, b_load) {
    if ("function" !== typeof fun_callback) {
        return;
    }
    if ("string" !== typeof str_fun || 0 === str_fun.length) {
        return;
    }
    var obj_sdk_param = new mc_sdk_param();

    obj_sdk_param.set_param_clear();
    obj_sdk_param.set_cmd("SET_PARAM");
    obj_sdk_param.set_func(str_fun);
    for (var idx = 0; idx < arr_param.length; idx++) {
        var obj_param = arr_param[idx];

        obj_sdk_param.set_param_value(obj_param.str_idx, obj_param.str_offset_msg);
        if (b_load) {
            obj_sdk_param.set_attr_val(obj_param.str_idx, "MEMTYPE", "FLS");
        }
    }
    $.post("/access_shell", obj_sdk_param.get_json(), function (response, status) {
        if ("success" !== status) {
            fun_callback("");
            return;
        }
        obj_sdk_param.set_param_clear();
        obj_sdk_param.set_json(response);
        fun_callback(obj_sdk_param.get_param_value("ERROR_CODE"));
        return;
    });
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    发送SNEDCARD/HUBCARD图像信息
 * 参数:
 *    @param { Promise<String> } str_fun func
 *    @param { Promise<Array> } arr_param 请求参数数组对象
 *    @param { Promise<Function> } fun_callback 回调函数
 *    @param { Promise<Boolean> } b_load 是否固化
 * 备注:
 * 参数 arr_param =[{
 *     PARAM:"索引",
 *     STR_IMG:"图像信息"
 *     },,]
 * 返回：
 *    NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.9.13
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_set_cards_img_rect(str_fun, arr_param, fun_callback, b_load) {
    if ("function" !== typeof fun_callback) {
        return;
    }
    if ("string" !== typeof str_fun || 0 === str_fun.length) {
        return;
    }
    var obj_sdk_param = new mc_sdk_param();

    obj_sdk_param.set_param_clear();
    obj_sdk_param.set_cmd("SET_PARAM");
    obj_sdk_param.set_func(str_fun);
    for (var idx = 0; idx < arr_param.length; idx++) {
        var obj_param = arr_param[idx];

        obj_sdk_param.set_param_value(obj_param.PARAM, obj_param.STR_IMG);
        if (b_load) {
            obj_sdk_param.set_attr_val(obj_param.PARAM, "MEMTYPE", "FLS");
        }
    }
    $.post("/access_shell", obj_sdk_param.get_json(), function (response, status) {
        if ("success" !== status) {
            fun_callback("");
            return;
        }
        obj_sdk_param.set_param_clear();
        obj_sdk_param.set_json(response);
        fun_callback(obj_sdk_param.get_param_value("ERROR_CODE"));
        return;
    });
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    发送SNEDCARD巡检信息
 * 参数:
 *    @param { Promise<Array> } arr_param 请求参数数组对象
 *    @param { Promise<Function> } fun_callback 回调函数
 *    @param { Promise<Boolean> } b_load 是否固化
 * 备注:
 * 参数 arr_param ={
 *     str_idx:"索引",
 *     str_offset_msg:"偏移信息",
 *     str_autocheck_msg:"巡检信息",
 *     str_chtrlchip_name:"芯片信息",
 *     }
 * 返回：
 *    NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.28
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_req_sendcard_autochecks(arr_param, fun_callback, b_load) {
    if (!Array.isArray(arr_param) || 0 === arr_param.length) {
        return;
    }
    if ("function" !== typeof fun_callback) {
        return;
    }
    var obj_sdk_param = new mc_sdk_param();

    obj_sdk_param.set_param_clear();
    obj_sdk_param.set_cmd("SET_PARAM");
    obj_sdk_param.set_func("HW_SENDCARD_AUTOCHECK");
    for (var idx = 0; idx < arr_param.length; idx++) {
        var obj_param = arr_param[idx];

        obj_sdk_param.set_param_value(String(idx), obj_param.str_idx);
        obj_sdk_param.set_attr_val(String(idx), "IMG_RECT", obj_param.str_autocheck_msg);
        if ("string" === typeof obj_param.str_chtrlchip_name && "" !== obj_param.str_chtrlchip_name) {
            obj_sdk_param.set_attr_val(String(idx), "CHIPNAME", obj_param.str_chtrlchip_name);
        }
        if (b_load) {
            obj_sdk_param.set_attr_val(String(idx), "MEMTYPE", "FLS");
        }
    }
    $.post("/access_shell", obj_sdk_param.get_json(), function (response, status) {
        if ("success" !== status) {
            fun_callback("");
            return;
        }
        obj_sdk_param.set_param_clear();
        obj_sdk_param.set_json(response);
        fun_callback(obj_sdk_param.get_param_value("ERROR_CODE"));
        return;
    });
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    发送请求构造卡数据数组
 * 参数:
 *     @param {Promise<Object>} obj_req_param 参数hub值队列
 *     @param {Promise<Function>} fun_callback 回调
 *     @param {Promise<Object>} obj_nosend_recv 不符合备份状态接收卡KEY
 * 返回：
 *     @returns {Promise<Function>}
 *      fun_callback(false) 参数有误
 *      fun_callback([data]) data卡数据数组
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.11
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_req_construct_carddata(obj_req_param, fun_callback, obj_nosend_recv) {
    if ("object" !== typeof obj_req_param || "function" !== typeof fun_callback) {
        return fun_callback(false);
    }

    var arr_sendcard = obj_req_param.sendcard;
    var arr_hubcard = obj_req_param.hubcard;
    var obj_recvcard = obj_req_param.recvcard;
    var arr_req_data;
    var arr_data = [];
    // 发送卡HUB卡port所在位置
    var obj_port_pot = {
        sendport: [],
        hubport: [],
        recvcard: []
    };

    if (0 === arr_sendcard.length) {
        return fun_callback(1);
    }

    var arr_params = [arr_sendcard, arr_sendcard, arr_hubcard, arr_hubcard];
    var arr_func = ["HW_SENDCARD_IMG_RECT", "HW_SENDCARD_OUTPORT_IMG_RECT", "HW_HUBCARD_IMG_RECT", "HW_HUBCARD_OUTPORT_IMG_RECT"];
    var str_data_name = ["SENDCARD", "SENDPORT", "HUB", "HUBPORT"];

    get_img_rect(0, arr_params.length);

    // 请求：发送卡、发送卡输出端口、HUB卡输出端口图像信息
    function get_img_rect(ui_idx, ui_total) {
        if (ui_idx < ui_total) {
            var arr_card_param = arr_params[ui_idx];

            if (0 === arr_card_param.length) {
                get_img_rect(++ui_idx, ui_total);
            }
            mc_req_img_rect(arr_func[ui_idx], arr_card_param, function (str_sendport_json) {
                var arr_handle_data = mc_handle_req_data(arr_card_param, str_sendport_json, arr_data, str_data_name[ui_idx], obj_port_pot);

                arr_data = arr_handle_data[0];
                obj_port_pot = arr_handle_data[1];
                get_img_rect(++ui_idx, ui_total);
            });
        } else {
            save_recvcard_data();
        }
    }

    function save_recvcard_data() {
        var arr_key = Object.keys(obj_recvcard);

        for (var idx = 0; idx < arr_key.length; idx++) {
            var str_key = arr_key[idx];
            var arr_param = arr_key[idx].split("_");
            var str_port_idx = arr_param[0];
            var ui_recv_idx = Number(arr_param[1]);
            var b_add_param = true;

            if (obj_nosend_recv[str_key]) {
                b_add_param = false;
            }
            if (-1 === str_port_idx.indexOf(":")) {
                // 处理此输出端口不存在情况
                if (!arr_data[Number(str_port_idx)].CHILD[ui_recv_idx]) {
                    arr_data[Number(str_port_idx)].CHILD[ui_recv_idx] = mc_fm_obj_data(false, "SENDPORT");
                    obj_port_pot.sendport = mc_save_use_mod_name(str_port_idx, obj_port_pot.sendport);
                }
                arr_data[Number(str_port_idx)].CHILD[ui_recv_idx].CHILD = obj_recvcard[str_key];
                if (b_add_param) {
                    obj_port_pot.recvcard.push(str_port_idx + ":" + ui_recv_idx);
                }
            } else {
                // 此接收卡在HUB输出端口下
                var arr_param_hub = str_port_idx.split(":");

                if (!arr_data[Number(arr_param_hub[0])].CHILD[Number(arr_param_hub[1])].CHILD[Number(arr_param_hub[2])].CHILD[ui_recv_idx]) {
                    arr_data[Number(arr_param_hub[0])].CHILD[Number(arr_param_hub[1])].CHILD[Number(arr_param_hub[2])].CHILD[ui_recv_idx] = mc_fm_obj_data(false, "HUBPORT");
                    obj_port_pot.hubport = mc_save_use_mod_name(Number(arr_param_hub[0]) + ":" + Number(arr_param_hub[1]) + ":" + Number(arr_param_hub[2]), obj_port_pot.hubport);
                }
                arr_data[Number(arr_param_hub[0])].CHILD[Number(arr_param_hub[1])].CHILD[Number(arr_param_hub[2])].CHILD[ui_recv_idx].CHILD = obj_recvcard[str_key];
                if (b_add_param) {
                    obj_port_pot.recvcard.push(arr_param_hub[0] + ":" + arr_param_hub[1] + ":" + arr_param_hub[2] + ":" + ui_recv_idx);
                }
            }
        }
        arr_req_data = $.extend(true, [], arr_data);

        // 计算数据：图像尺寸对齐，网口区域对齐
        arr_data = mc_card_pos(arr_data, parent.b_if_reset_port, parent.G_B_NET_RESET_ZERO);
        // console.log(arr_data);
        return fun_callback(arr_data, obj_port_pot, arr_req_data);
    }
    return fun_callback([]);
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    请求：发送卡图像信息、发送卡输出端口、HUB卡图像信息、HUB卡输出端口图像信息
 * 参数:
 *     @param {Promise<String>} str_sunc func
 *     @param {Promise<Array>} arr_idx 当前需请求数据卡下标数组
 *     @param {Promise<Function>} fun_callback 回调函数
 * 返回：
 *     NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.11
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_req_img_rect(str_sunc, arr_idx, fun_callback) {
    if ("string" !== typeof str_sunc || 0 === str_sunc.length) {
        return;
    }
    if ("function" !== typeof fun_callback) {
        return;
    }
    if (!(Array.isArray(arr_idx)) || 0 === arr_idx.length) {
        return;
    }
    var obj_sdk_param = new mc_sdk_param();

    obj_sdk_param.set_param_clear();
    obj_sdk_param.set_cmd("GET_PARAM");
    // HW_SENDCARD_IMG_RECT
    obj_sdk_param.set_func(str_sunc);

    for (var idx = 0; idx < arr_idx.length; idx++) {
        obj_sdk_param.set_param_value(arr_idx[idx], "");
    }
    $.post("/access_shell", obj_sdk_param.get_json(), function (response, status) {
        if ("success" !== status) {
            fun_callback("");
            return;
        }

        fun_callback(response);
        return;
    });
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取未超载卡索引
 * 参数:
 *     @param {Promise<Array>} arr_req 请求构造数据
 *     @param {Promise<Array>} arr_count 计算后数据
 *     @param {Promise<Object>} obj_pot 发送卡HUB卡port口所在位置
 *     @param {Promise<Function>} fn_callback 回调函数
 * 备注: 回调函数参数
 *      // 返回对象 不超载卡索引 无需发送
 *      obj_unload = {
 *          "sendcard": [],
 *           "hubcard": []
 *       };
 * 返回：
 *     @returns {Promise<Boolean>}
 *      false 参数有误
 *      true 获取成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.11
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_card_data_judge(arr_req, arr_count, obj_pot, fn_callback) {
    if ("[object Object]" !== Object.prototype.toString.call(obj_pot) || "[object Array]" !== Object.prototype.toString.call(arr_count) || "[object Array]" !== Object.prototype.toString.call(arr_req)) {
        return false;
    }
    // req 发送卡port口数据
    var arr_req_sendcard_port = mc_req_img_str(mc_recvcard_req_data(arr_req, obj_pot.sendport));
    // hub卡数据
    var arr_req_hubcard_port = mc_req_img_str(mc_recvcard_req_data(arr_req, obj_pot.hubport));
    var arr_count_hubcard = mc_recvcard_req_data(arr_count, obj_pot.hubport, true);
    // 进行超载测试数据
    var ary_sendcard_load_data = mc_card_load_data(arr_req_sendcard_port, arr_count);
    var ary_hubcard_load_data = mc_card_load_data(arr_req_hubcard_port, arr_count_hubcard);
    // 不超载卡 添加标识 无需发送
    var obj_unload = {
        "sendcard": [],
        "hubcard": []
    };
    // hub false检测已完成
    var b_check_hub = true;

    if (0 === ary_sendcard_load_data.length) {
        b_check_hub = false;
        card_load_check(ary_hubcard_load_data, "HUBCARD_LIST", fn_callback);
    } else {
        card_load_check(ary_sendcard_load_data, "SENDCARD_LIST", fn_callback);
    }

    // 当前测试卡数据 当前需要获取卡列表参数
    function card_load_check(ary_data, str_func, fun_callback) {
        if (0 === ary_data.length || !b_check_hub) {
            fun_callback(obj_unload);
            return;
        }
        var obj_c = new format_card_output_load();
        var ui_type = 2;
        var str_card_first_name = str_sendcard_first_name;

        for (var idx_card = 0; idx_card < ary_data.length; idx_card++) {
            var obj_data = ary_data[idx_card];

            obj_c.set_obj_param(String(obj_data.NAME_ID), String(obj_data.POS_VAL), String(obj_data.WIDTH), String(obj_data.HEIGHT));
        }
        if ("HUBCARD_LIST" === str_func) {
            ui_type = 1;
            b_check_hub = false;
            str_card_first_name = str_hubcard_first_name;
        }
        // 请求发送卡列表first name
        if (0 === str_card_first_name.length) {
            mc_get_req_card_list(str_func, function (str_name) {
                if ("string" === typeof str_name && 0 !== str_name.length) {
                    get_outport_load(ui_type, str_name, obj_c, ary_data, fun_callback);
                } else {
                    // 获取不到卡列表
                    if (2 === ui_type) {
                        b_sendcard_getname_success = false;
                    } else {
                        b_hubcard_getname_success = false;
                    }
                }
            });
        } else {
            get_outport_load(ui_type, str_card_first_name, obj_c, ary_data, fun_callback);
        }
    }

    // 获取对应输出口图像负荷
    function get_outport_load(type, str_name, obj_card, ary_data, fun_callback) {
        mc_get_card_outport_load(type, str_name, obj_card, function (b_failes, str_json) {
            if (!b_failes) {
                var str_type = "";
                var obj_sdk_param = new mc_sdk_param();

                if (1 === type) {
                    str_type = "hubcard";
                }
                if (2 === type) {
                    str_type = "sendcard";
                }

                obj_sdk_param.set_param_clear();
                obj_sdk_param.set_json(str_json);
                for (var idx_card = 0; idx_card < ary_data.length; idx_card++) {
                    var obj_param = ary_data[idx_card];
                    // 负荷百分比
                    var str_val = obj_sdk_param.get_param_value(obj_param.NAME_ID);

                    // 记录未超载卡索引
                    if (100 >= Number(str_val)) {
                        obj_unload[str_type].push(obj_param.POS_VAL);
                    }
                }
            }
            if (b_check_hub) {
                // hub输出卡图像负荷
                card_load_check(ary_hubcard_load_data, "HUBCARD_LIST", fun_callback);
            } else {
                fun_callback(obj_unload);
                return;
            }
        });
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取HUB卡/send card列表 1名称
 * 参数:
 *     @param {Promise<String>} str_func fun
 *     @param {Promise<Function>} fun_callback
 * 返回：
 *     NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.25
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_req_card_list(str_func, fun_callback) {
    if ("[object String]" !== Object.prototype.toString.call(str_func) || "[object Function]" !== Object.prototype.toString.call(fun_callback)) {
        return;
    }
    var obj_sdk_param = new mc_sdk_param();

    obj_sdk_param.set_param_clear();
    obj_sdk_param.set_cmd("GET_PARAM");
    obj_sdk_param.set_func(str_func);
    $.post("/access_shell", obj_sdk_param.get_json(), function (response, status) {
        if ("success" !== status) {
            if ("SENDCARD_LIST" === str_func) {
                b_sendcard_getname_success = false;
            } else {
                b_hubcard_getname_success = false;
            }
            fun_callback("");
            return;
        }
        obj_sdk_param.set_param_clear();
        obj_sdk_param.set_json(response);

        var str_card_name = obj_sdk_param.get_param_value(obj_sdk_param.get_param_name(0));

        if ("SENDCARD_LIST" === str_func) {
            str_sendcard_first_name = str_card_name;
        } else {
            str_hubcard_first_name = str_card_name;
        }

        fun_callback(str_card_name);
        return;
    });
}


// -------------------------------------------数据处理----------------------------------------------
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取发送箱体偏移及配置信息时 工作模式参数
 * 参数:
 *    @param { Promise<Boolean> } b_load 是否固化
 * 返回：
 *    @return { Promise<String> }
 *     str_workmode 工作模式参数字串
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.01.05
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_req_workmode_data(b_load) {
    var b_mass = parent.b_if_mass;
    var b_mirror = parent.b_if_mirror;
    var str_workmode = "0";

    if (b_mass) {
        str_workmode = "1";
    }
    if (b_mass && b_mirror && b_load) {
        str_workmode = "3";
    }
    return str_workmode;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    请求数据格式
 * 参数:
 *    NA
 * 返回：
 *    NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.28
 *      内容 : 所有代码
 ************************************************************************************************/
function format_req_param() {
    this.str_idx = "";
    this.str_offset_msg = "";
    this.str_chtrlchip_name = "";
    this.str_autocheck_msg = "";
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    卡类输出端口(sendcaradport/hubcardport)图像配置请求参数
 * 参数:
 *    @param { Promise<Array> } arr_data 数据对象数组
 *    @param { Promise<Boolean> } b_hubport 是否为HUBCARD
 * 返回：
 *    @return { Promise<Array> }
 *     arr_result
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.28
 *      内容 : 所有代码
 ************************************************************************************************/
function get_card_port_reqdata(arr_data, b_hubport) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_data) || "[object Boolean]" !== Object.prototype.toString.call(b_hubport)) {
        return [];
    }
    var arr_result = [];

    for (var idx = 0; idx < arr_data.length; idx++) {
        var obj_req = new format_req_param();
        var obj_data = arr_data[idx];
        var str_idx = obj_data.PARAM;

        if (b_hubport) {
            str_idx = "(" + str_idx + ")";
        }
        obj_req.str_idx = str_idx;
        obj_req.str_offset_msg = obj_data.STR_IMG;
        arr_result.push(obj_req);
    }
    return arr_result;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    处理请求数据 构造对应个数数据字串 ->计算格式
 * 参数:
 *    @param { Promise<Array> } arr_param 请求参数数组
 *    @param { Promise<String> } str_json 请求获取json字串
 *    @param { Promise<Array> } arr_data 对应格式数据
 *    @param { Promise<String> } str_type 数据类型
 *    @param { Promise<Object> } obj_port_pot 发送卡HUB卡port所在位置
 * 返回：
 *    @return { Promise<Array> }
 *     [arr_data,obj_port_pot]
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.28
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_handle_req_data(arr_param, str_json, arr_data, str_type, obj_port_pot) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_param) || "[object String]" !== Object.prototype.toString.call(str_json)) {
        return false;
    }
    if ("[object Array]" !== Object.prototype.toString.call(arr_data) || "[object String]" !== Object.prototype.toString.call(str_type)) {
        return false;
    }
    var obj_sdk_param = new mc_sdk_param();

    obj_sdk_param.set_param_clear();
    obj_sdk_param.set_json(str_json);
    var ui_cnt = obj_sdk_param.get_param_cnt();

    for (var idx_cnt = 0; idx_cnt < ui_cnt; idx_cnt++) {
        var str_param_key = arr_param[idx_cnt];

        if (!str_param_key) {
            continue;
        }
        var str_img_msg = obj_sdk_param.get_param_value(str_param_key);

        if ("string" === typeof str_img_msg) {
            if ("SENDPORT" === str_type) {
                if (0 === str_img_msg.length) {
                    // create default
                    arr_data[Number(str_param_key)].CHILD[0] = mc_fm_obj_data(false, str_type);
                } else {
                    arr_data[Number(str_param_key)] = get_child(str_img_msg, str_type, arr_data[Number(str_param_key)]);
                }
                obj_port_pot.sendport.push(str_param_key);
            } else {
                if (-1 === str_param_key.indexOf(":")) {
                    // SENDCARD
                    arr_data[Number(str_param_key)] = get_card_data(str_img_msg, str_type);
                } else {
                    if ("HW_HUBCARD_IMG_RECT" === obj_sdk_param.get_func()) {
                        // HUBCARD
                        var arr_hub_param = str_param_key.split(":");
                        var obj_hub = get_card_data(str_img_msg, str_type);
                        var ui_hubport_idx = Number(arr_hub_param[2]);

                        obj_port_pot.hubport.push(Number(arr_hub_param[0]) + ":" + Number(arr_hub_param[1]) + ":" + ui_hubport_idx);
                        // 处理hub所在发送卡输出端口不存在情况
                        if (!arr_data[Number(arr_hub_param[0])].CHILD[Number(arr_hub_param[1])]) {
                            arr_data[Number(arr_hub_param[0])].CHILD[Number(arr_hub_param[1])] = mc_fm_obj_data(false, "SENDPORT");
                        }
                        arr_data[Number(arr_hub_param[0])].CHILD[Number(arr_hub_param[1])].CHILD[ui_hubport_idx] = obj_hub;
                    } else {
                        // HUBPORT
                        var arr_hubport_param = str_param_key.split(":");
                        var arr_hub_port = get_child(str_img_msg, "HUBPORT", []);
                        // // 构造HUB数据 存入HUBport数据
                        // var obj_hub = mc_fm_obj_data(false, "HUB");

                        // obj_port_pot.hubport.push(Number(arr_hubport_param[0]) + ":" + Number(arr_hubport_param[1]) + ":" + Number(arr_hubport_param[2]));
                        // obj_hub.CHILD = arr_hub_port;
                        // // 处理hub所在发送卡输出端口不存在情况
                        // if (!arr_data[Number(arr_hubport_param[0])].CHILD[Number(arr_hubport_param[1])]) {
                        //     arr_data[Number(arr_hubport_param[0])].CHILD[Number(arr_hubport_param[1])] = mc_fm_obj_data(false, "SENDPORT");
                        // }
                        arr_data[Number(arr_hubport_param[0])].CHILD[Number(arr_hubport_param[1])].CHILD[Number(arr_hubport_param[2])].CHILD = arr_hub_port;
                    }
                }
            }
        }
    }


    function get_child(s_img_msg, s_type, arr_result) {
        var ary_port_img = s_img_msg.split(",");

        for (var ui_index = 0; ui_index < ary_port_img.length; ui_index++) {
            if ("HUBPORT" === s_type) {
                arr_result.push(mc_fm_obj_data(ary_port_img[ui_index], s_type));
            } else {
                arr_result.CHILD[ui_index] = mc_fm_obj_data(ary_port_img[ui_index], s_type);
            }
        }
        return arr_result;
    }

    // 获取卡数据 添加参数EN_IN_RECT：是否支持图像配置
    function get_card_data(str_img, s_type) {
        var EN_IN_RECT = true;
        var obj_sendcard_data = mc_fm_obj_data(str_img, s_type);

        if ("" === str_img) {
            EN_IN_RECT = false;
        }
        obj_sendcard_data.EN_IN_RECT = EN_IN_RECT;
        return obj_sendcard_data;
    }
    return [arr_data, obj_port_pot];
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    超载测试数据构造
 * 参数:
 *    @param { Promise<Array> } arr_req_port 请求卡port数据数组
 *    @param { Promise<Array> } arr_count_card 计算卡数据对象数组
 * 返回：
 *    @return { Promise<Array> }
 *     arr_card_load_data
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.28
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_card_load_data(arr_req_port, arr_count_card) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_req_port) || "[object Array]" !== Object.prototype.toString.call(arr_count_card)) {
        return false;
    }
    var arr_card_load_data = [];

    for (var idx_card = 0; idx_card < arr_req_port.length; idx_card++) {
        var obj_req_port_img = arr_req_port[idx_card];
        var obj_count_card = arr_count_card[idx_card];

        if (obj_req_port_img && obj_count_card) {
            // 获取请求发送卡图像数据
            var str_req_card_img = mc_basis_output_get_img(obj_req_port_img.STR_IMG);
            // (X:Y:W:H) -> [X,Y,W,H]
            var arr_req_img = mc_fm_img_rece(str_req_card_img);
            // 对比数据
            var b_load_check = mc_img_data_compare(obj_count_card, arr_req_img);

            if (b_load_check) {
                var obj_load_data = {
                    NAME_ID: String(idx_card),
                    POS_VAL: obj_req_port_img.PARAM,
                    WIDTH: arr_req_img[2],
                    HEIGHT: arr_req_img[3]
                };

                arr_card_load_data.push(obj_load_data);
            }
        }
    }
    return arr_card_load_data;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    卡图像数据比较
 * 参数:
 *    @param { Promise<Object> } obj_count 计算后数据对象
 *    @param { Promise<Array> } arr_req_img 当前比较卡图像
 * 返回：
 *    @return { Promise<Boolean> }
 *     true:进行超载测试
 *     false:直接发送计算结果
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.28
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_img_data_compare(obj_count, arr_req_img) {
    if ("[object Object]" !== Object.prototype.toString.call(obj_count) || "[object Array]" !== Object.prototype.toString.call(arr_req_img)) {
        return false;
    }
    // 计算结果在预设范围
    // if (Number(obj_count.X) > Number(arr_req_img[0]) && Number(obj_count.Y) > Number(arr_req_img[1]) && Number(obj_count.W) > Number(arr_req_img[2]) && Number(obj_count.H) > Number(arr_req_img[3])) {
    //     return true;
    // }
    // if (Number(obj_count.X) === Number(arr_req_img[0]) && Number(obj_count.Y) === Number(arr_req_img[1]) && Number(obj_count.W) === Number(arr_req_img[2]) && Number(obj_count.H) === Number(arr_req_img[3])) {
    //     return true;
    // }
    // if (Number(obj_count.X) === Number(arr_req_img[0]) && Number(obj_count.Y) === Number(arr_req_img[1]) && Number(obj_count.W) === Number(arr_req_img[2]) && Number(obj_count.H) === Number(arr_req_img[3])) {
    //     return true;
    // }
    // if (Number(obj_count.X) >= Number(arr_req_img[0]) && Number(obj_count.Y) >= Number(arr_req_img[1]) && Number(obj_count.W) < Number(arr_req_img[2]) && Number(obj_count.H) < Number(arr_req_img[3])) {
    //     return true;
    // }
    var u_cntx = Number(obj_count.X);
    var u_cnty = Number(obj_count.Y);
    var u_cntw = Number(obj_count.W);
    var u_cnth = Number(obj_count.H);
    var u_reqx = Number(arr_req_img[0]);
    var u_reqy = Number(arr_req_img[1]);
    var u_reqw = Number(arr_req_img[2]);
    var u_reqh = Number(arr_req_img[3]);

    // 计算后数据左右上角均在请求数据中 = 在预算范围
    if (u_cntx <= u_reqx && u_cnty <= u_reqy && u_cntx + u_cntw <= u_reqx + u_reqw && u_cnty + u_cnth <= u_reqy + u_reqh) {
        return true;
    }
    return false;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取请求参数对象
 * 参数:
 *     @param {Promise<Object>} obj_same_hub_queue 参数hub值队列
 *     @param {Promise<Function>} fun_callback 回调
 *     @param {Promise<Object>} obj_card_filter 卡过滤数据
 *     @param {Promise<boolean>} b_if_need_recv 是否需要一致卡才进行调用 默认false
 *     @param {Promise<Object>} obj_backup 符合备份条件发送卡输出口  {"0:1":true,"0:0":true} 可选若无不比较此项
 * 返回：
 *     @returns {Promise<Function>}
 *      false 参数有误
 *      obj_param = {
 *          sendcard: [], // 发送卡参数字串
 *          hubcard: [], //hub卡参数字串
 *          recvcard: {} // 接收卡参数字串
 *      };
 * 备注:
 *    obj_card_filter = { card_order: 选择的卡指令, card_type: 接收卡类型 }
 *    符合备份条件指：控制接收卡的发送，符合条件接收卡发送偏移 主控、分控图像信息仍然发送
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.9
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_fm_req_param_data(obj_same_hub_queue, fun_callback, obj_card_filter, b_if_need_recv, obj_backup) {
    if ("function" !== typeof fun_callback) {
        return fun_callback(false);
    }
    var obj_param = {
        sendcard: [],
        hubcard: [],
        recvcard: {}
    };

    var arr_key = Object.keys(obj_same_hub_queue);
    var b_return = check_data_key(arr_key);
    // 不符合备份接收卡KEY
    var obj_nosend_recv = {};

    if (!b_return) {
        return fun_callback(false);
    }
    for (var idx_key = 0; idx_key < arr_key.length; idx_key++) {
        var str_key = arr_key[idx_key];

        // 跳过未设置卡
        if ("?" === str_key) {
            continue;
        }
        var arr_recv = obj_same_hub_queue[str_key];
        var arr_param = mc_get_data_param(str_key.split(":")[0], 0, 1);
        var str_param = arr_param[0];
        var str_recv_param = "";
        var b_backup = true;

        if (0 === arr_recv.length) {
            continue;
        }
        // 不符合备份条件跳过 筛选其他信息 若其余信息满足发送主控分控图像信息
        if ("[object Object]" === Object.prototype.toString.call(obj_backup) && ((3 === arr_param[1] && !obj_backup[str_param.substr(0, str_param.lastIndexOf(":"))]) || (2 === arr_param[1] && !obj_backup[str_param]))) {
            b_backup = false;
        }

        // 筛选数据：卡列表下标
        if (obj_card_filter && "[object Object]" === Object.prototype.toString.call(obj_card_filter)) {
            if (!mc_filter_data_is_eligible(obj_card_filter.card_order, str_key)) {
                continue;
            }
        }

        for (var idx_box = 0; idx_box < arr_recv.length; idx_box++) {
            var obj_box = arr_recv[idx_box];
            var str_chip_name = obj_box.children(".mod_msg_box").children(".chip_name").text();

            // 筛选数据：芯片类型和下标
            if (obj_card_filter && "[object Object]" === Object.prototype.toString.call(obj_card_filter)) {
                var ui_receive = Number(obj_card_filter.card_order.split(":")[4]);

                // 1.compare receive card index
                if (-1 !== ui_receive) {
                    if (ui_receive !== idx_box) {
                        continue;
                    }
                }

                // new card type
                if ("ALL" === str_chip_name) {
                    str_chip_name = obj_card_filter.card_type;
                }

                // 2.compare receive card type
                if (str_chip_name !== obj_card_filter.card_type && !b_if_need_recv) {
                    continue;
                }
                // 硬件存在选项卡则发选项 无则发界面的卡
                // if (obj_card_filter.card_type) {
                //     str_chip_name = obj_card_filter.card_type;
                // }
            }
            var ary_recv = mc_sendoffset_handle_compose_data(obj_box, str_chip_name);

            str_recv_param = Number(str_key.split(":")[1].slice(1)) - 1;
            for (var z = 0; z < ary_recv.length; z++) {
                var obj_data = ary_recv[z];
                var obj_recv_data = mc_set_obj_ary_date(obj_param.recvcard, str_param + "_" + str_recv_param, obj_data);

                if (1 === arr_param[1]) {
                    obj_param.sendcard = mc_save_use_mod_name(str_param, obj_param.sendcard);
                    // obj_param.recvcard = mc_set_obj_ary_date(obj_param.recvcard, str_param + "_" + str_recv_param, obj_data);
                } else {
                    obj_param.sendcard = mc_save_use_mod_name(str_param.substring(0, str_param.indexOf(":")), obj_param.sendcard);
                    obj_param.hubcard = mc_save_use_mod_name(str_param, obj_param.hubcard);
                    // obj_param.recvcard = mc_set_obj_ary_date(obj_param.recvcard, str_param + "_" + str_recv_param, obj_data);
                }
                obj_param.recvcard = obj_recv_data;
                if (!b_backup) {
                    // obj_nosend_recv = obj_recv_data;
                    obj_nosend_recv = mc_set_obj_ary_date(obj_nosend_recv, str_param + "_" + str_recv_param, obj_data);
                }
            }
        }
    }
    mc_req_construct_carddata(obj_param, fun_callback, obj_nosend_recv);
    return true;

    function check_data_key(ary_key) {
        if (0 === ary_key.length) {
            return false;
        }

        if (1 === ary_key.length && "?" === ary_key[0]) {
            return false;
        }
        return true;
    }
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    筛选页面块(大屏箱体)数据是否符合(发送 || 固化)条件
 * 参数:
 *    @param { Promise<String> } str_card_order 筛选条件 === 指令格式的卡字串
 *    @param { Promise<String> } str_key 被筛选的对象的key
 * 返回:
 *    @returns { Promise<Boolean>} true === 符合条件 || false === 不符合
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-11-14
 *       内容 : 所有代码
 ************************************************************************************************/
function mc_filter_data_is_eligible(str_card_order, str_key) {
    if ("string" !== typeof str_card_order || "string" !== typeof str_key) {
        return false;
    }

    if ("" === str_card_order.trim()) {
        return false;
    }

    var arr_card_list_seque = str_card_order.split(":");
    var ui_compare_len = 3;
    var arr_box_card = mc_get_line_key_val(str_key, b_add_screen);

    if (!one_to_one_compare(ui_compare_len, arr_card_list_seque, arr_box_card)) {
        return false;
    }


    /************************************************************************************************
* 类型:
*    函数
* 功能:
*    一对一比较
* 参数:
*    @param { Promise<Number> } ui_idx 需要比较到的数组下标(0 -> ui_idx 包含ui_idx)
*    @param { Promise<Array> } arr_condition 条件数组
*    @param { Promise<Array> } arr_entity 实体数组
* 返回:
*    @returns { Promise<Boolean> } true === 符合 || false === 不符合
* 例子:
*    NA
* 备注:
*    条件数组为卡命令字符串拆分的数组，因此每一项的值需要+1;
* 修改:
*    1. 类型 : 创建
*       作者 : 巫昭雯
*       时间 : 2020-11-16
*       内容 : 所有代码
************************************************************************************************/
    function one_to_one_compare(ui_idx, arr_condition, arr_entity) {
        if ("object" !== typeof arr_condition && "object" !== typeof arr_entity || "number" !== typeof ui_idx) {
            return false;
        }

        for (var ui_i = 0; ui_i <= ui_idx; ui_i++) {
            var str_com = arr_condition[ui_i];
            var str_en = arr_entity[ui_i];

            // "-1" Means all
            if ("-1" === str_com) {
                continue;
            }

            // idx + 1 --> first card || first card port === 1
            if ((Number(str_com) + 1).toString() !== str_en) {
                return false;
            }
        }

        return true;
    }


    return true;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    设置数据对象中某一key的val值 该val值类型为数组
 * 参数:
 *     @param {Promise<Object>} obj_data 数据对象
 *     @param {Promise<String>} str_key 指定key
 *     @param {Promise<String>} str_val 对应val数组中所要添加的项
 * 返回：
 *     @returns {Promise<Object>}
 *      false 参数有误
 *      obj_data
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.10
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_set_obj_ary_date(obj_data, str_key, str_val) {
    if ("object" !== typeof obj_data) {
        return obj_data;
    }
    if (obj_data[str_key]) {
        obj_data[str_key].push(str_val);
    } else {
        obj_data[str_key] = [str_val];
    }
    return obj_data;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取矫正后的接收卡PORT数据对象
 * 参数:
 *     @param {Promise<Array>} arr_data 卡数据数组
 *     @param {Promise<Array>} arr_pot 接收卡所在位置字串
 *     @param {Promise<Boolean>} b_card 获取卡数据 可为空
 * 返回：
 *     @returns {Promise<Object>}
 *      obj_recv
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.11
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_recvcard_req_data(arr_data, arr_pot, b_card) {
    if (!(Array.isArray(arr_data)) || 0 === arr_data.length) {
        return false;
    }
    var obj_recv = {};
    var arr_card = [];

    if (b_card) {
        obj_recv = [];
    }

    for (var idx_pot = 0; idx_pot < arr_pot.length; idx_pot++) {
        var str_pot = arr_pot[idx_pot];
        var ary_pot = str_pot.split(":");
        var ary_recv = [];
        var ui_len = ary_pot.length;

        if (b_card) {
            ui_len -= 1;
            var str_card = str_pot.substr(0, str_pot.lastIndexOf(":"));
            var b_jump = false;

            for (var index_card = 0; index_card < arr_card.length; index_card++) {
                if (str_pot.substr(0, str_pot.lastIndexOf(":")) === arr_card[index_card]) {
                    b_jump = true;
                    break;
                }
            }
            if (b_jump) {
                continue;
            } else {
                arr_card.push(str_card);
            }
        }

        for (var idx = 0; idx < ui_len; idx++) {
            if (0 === idx) {
                if (!b_card && idx === ui_len - 1 && arr_data[Number(ary_pot[idx])].NO_SEND) {
                    ary_recv = [];
                } else {
                    ary_recv = arr_data[Number(ary_pot[idx])].CHILD;
                }
            } else if (!b_card && idx === ui_len - 1 && ary_recv[Number(ary_pot[idx])].NO_SEND) {
                // 此卡是否无需发送
                ary_recv = [];
            } else {
                ary_recv = ary_recv[Number(ary_pot[idx])].CHILD;
            }
        }
        if (2 === ary_pot.length) {
            str_pot += ":0:0";
        }
        if (b_card) {
            for (var idx_card = 0; idx_card < ary_recv.length; idx_card++) {
                obj_recv.push(ary_recv[idx_card]);
            }
        } else {
            obj_recv[str_pot] = ary_recv;
        }
    }
    return obj_recv;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    卡列表请求失败 处理接收卡请求参数数组
 * 参数:
 *     @param {Promise<Array>} arr_param 处理请求参数数组
 *     @param {Promise<Array>} arr_recv 接收卡请求参数数组
 *     @param {Promise<Boolean>} b_card 是否为设置卡 可为空
 * 返回：
 *     @returns {Promise<Array>}
 *      arr_recv
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.28
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_handle_recvcard_param(arr_param, arr_recv, b_card) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_param) || "[object Array]" !== Object.prototype.toString.call(arr_recv)) {
        return arr_recv;
    }
    for (var idx = 0; idx < arr_param.length; idx++) {
        if (b_card) {
            var ui_card = 0;

            while (ui_card < arr_recv.length) {
                if (arr_param[idx] === arr_recv[ui_card]) {
                    arr_recv.splice(ui_card, 1);
                } else {
                    ui_card++;
                }
            }
        } else {
            var ary_param = arr_param[idx].split(":");

            if (3 === ary_param.length) {
                var index = 0;

                while (index < arr_recv.length) {
                    var ary_recv = arr_recv[index].split(":");

                    if (4 === ary_recv.length) {
                        arr_recv.splice(index, 1);
                    } else {
                        index++;
                    }
                }
            }
        }
    }
    return arr_recv;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    未超载卡无需发送 处理请求参数
 * 参数:
 *     @param {Promise<Object>} obj_unsend 无需发送卡参数对象
 *     @param {Promise<Object>} obj_port_pot 请求参数对象
 *     @param {Promise<Function>} fn_callback
 * 返回：
 *     NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.28
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_handle_param(obj_unsend, obj_port_pot, fn_callback) {
    var ary_sendcard = obj_unsend.sendcard;
    var ary_hubcard = obj_unsend.hubcard;

    if (0 !== ary_sendcard.length) {
        obj_port_pot.sendport = mc_handle_recvcard_param(ary_sendcard, obj_port_pot.sendport, true);
    }

    if (!b_hubcard_getname_success) {
        // HUB卡列表不存在时 处理参数 ---不发送
        obj_port_pot.recvcard = mc_handle_recvcard_param(obj_port_pot.hubport, obj_port_pot.recvcard);
        obj_port_pot.hubport = [];
    } else {
        if (0 !== ary_hubcard.length) {
            obj_port_pot.sendport = mc_handle_recvcard_param(ary_hubcard, obj_port_pot.hubport, true);
        }
    }
    fn_callback(obj_port_pot);
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    图像信息转化为指定数据对象
 * 参数:
 *     @param {Promise<Array>} str_img 图像信息
 *     @param {Promise<Array>} str_name 卡name
 * 返回：
 *     @returns {Promise<Object>}
 *      obj_data
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.11
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_fm_obj_data(str_img, str_name) {
    if ("string" !== typeof str_img || 0 === str_img.length) {
        return {
            NAME: str_name,
            X: 0,
            Y: 0,
            W: 1,
            H: 1,
            CHILD: []
        };
    }
    // (X:Y:W:H) -> [X,Y,W,H]
    var arr_img = mc_fm_img_rece(str_img);
    var obj_data = {
        NAME: str_name,
        X: Number(arr_img[0]),
        Y: Number(arr_img[1]),
        W: Number(arr_img[2]) || 1,
        H: Number(arr_img[3]) || 1,
        CHILD: []
    };

    return obj_data;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    构造输出端口请求字串
 * 参数:
 *     @param {Promise<Object>} obj_data
 * 返回：
 *     @returns {Promise<Array>}
 *      arr_return
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.11
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_req_img_str(obj_data) {
    if ("object" !== typeof obj_data) {
        return [];
    }

    var arr_key = Object.keys(obj_data);
    var arr_return = [];

    for (var idx_key = 0; idx_key < arr_key.length; idx_key++) {
        var str_param = arr_key[idx_key];
        var arr_img = obj_data[str_param];
        var str_img = "";

        for (var idx = 0; idx < arr_img.length; idx++) {
            var obj_img = arr_img[idx];

            if (obj_img) {
                str_img += "(" + obj_img.X + ":" + obj_img.Y + ":" + obj_img.W + ":" + obj_img.H + "),";
            }
        }
        str_img = str_img.slice(0, str_img.length - 1);
        arr_return.push({
            PARAM: str_param,
            STR_IMG: str_img
        });
    }

    return arr_return;
}

// 箱体配置信息参数构造、发送箱体基础数据------------------------------------
// handle data
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取箱体配置发送/固化数据
 * 参数:
 *     @param {Promise<Object>} obj_same_hub_queue 连线队列
 *     @param {Promise<Object>} obj_card_filter 筛选数据下标、芯片信息
 *     @param {Promise<Object>} obj_backup 符合备份条件发送卡输出口  {"0:1":true,"0:0":true}
 * 筛选条件：
 *     跳过未设置卡、新建卡
 *     跳过不符合备份条件端口下卡
 *     对比卡列表下标、芯片类型是否符合条件
 * 整合数据群发规则:
 *     检查PORT下卡是否群发 获取数据字串、群发队列标识
 *     更新PORT群发请求对应参数为"-1" 检查发送卡PORT是否群发、更新对应PORT口标识为"-1" 删除重复数据
 *     检查HUBPORT口是否群发 只剩下一条数据并且发送所有卡时 更新对应PORT口标识为"-1"
 * 返回：
 *     @returns {Promise<Object>}
 *      false 参数有误
 *      obj_send_data
 * 备注：
 *      obj_send_data = [
 *          {
 *              idx: "(SEDN_IDX:SEND_PORT:HUB:HUB_PORT:RECV_IDX)",
 *              data: {
 *                  str_rotation: "(0:0:angle)",
 *                  str_mirror: "0",
 *                  str_scale: "(0:0:Xs:Ys)",
 *                  str_size: "(W:H)", // 与变换无关
 *                  str_box_name: "mc_box_0",
 *                  str_chip_name: "FPGA"
 *              }
 *          },,
 *      ]
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.18
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_box_config_data(obj_same_hub_queue, obj_card_filter, obj_backup) {
    if ("[OBJECT OBJECT]" !== Object.prototype.toString.call(obj_same_hub_queue).toUpperCase()) {
        return [];
    }
    if ("[OBJECT OBJECT]" !== Object.prototype.toString.call(obj_card_filter).toUpperCase()) {
        return [];
    }
    if ("[OBJECT OBJECT]" !== Object.prototype.toString.call(obj_backup).toUpperCase()) {
        return [];
    }
    var arr_key = Object.keys(obj_same_hub_queue);
    // 硬件连接状态false时 HUB HUBPORT 索引置零
    var b_hardware_state = mc_get_top_data("B_HARDWARE_STATE");
    // 记录各卡出现次数
    var obj_card_cnt = {
        b_port: true,
        port: {},
        // "0:0":cnt
        hub_cnt: {},
        // "0:0:0":cnt
        hubport_cnt: {}
    };
    // 箱体宽高 {box_name:[w,h],,,} 避免重复获取
    var obj_box_size = {};
    var ARY_BOX_DATA = mc_get_top_data("ARY_BOX_DATA");
    var ARY_MOD_DATA = mc_get_top_data("ARY_MOD_DATA");
    // 整合数据{KEY:{idx:'',data:{}}} 每项为一组群发数据
    var obj_integration_data = {};
    // 整合之前长度
    var ui_intergration_before_len = 0;

    for (var i_key = 0; i_key < arr_key.length; i_key++) {
        var str_key = arr_key[i_key];
        var arr_line_data = obj_same_hub_queue[str_key];

        if (!str_key || "" === str_key || "?" === str_key || "[OBJECT ARRAY]" !== Object.prototype.toString.call(arr_line_data).toUpperCase() || 0 === arr_line_data.length) {
            continue;
        }
        var obj_param = mc_card_param_handle(str_key, b_hardware_state);
        var str_param = obj_param.str_param;
        var str_sendport = obj_param.str_sendport;

        add_data(obj_card_cnt.port, str_sendport.substr(0, str_sendport.lastIndexOf(":")));
        add_data(obj_card_cnt.hub_cnt, str_sendport);
        add_data(obj_card_cnt.hubport_cnt, str_param.substr(0, str_param.lastIndexOf(":")));

        // 筛选符合卡列表下标、符合备份信息卡
        if (!mc_filter_data_is_eligible(obj_card_filter.card_order, str_key) || !obj_backup[str_sendport]) {
            obj_card_cnt.b_port = false;
            continue;
        }
        var b_group_recv = true;
        var str_intergration_key = "";
        var ui_recv_len = arr_line_data.length;

        for (var i_recv = 0; i_recv < ui_recv_len; i_recv++) {
            var obj_jq = arr_line_data[i_recv];

            // 数据有误 || 过滤新建卡 || 筛选芯片类型和接收卡下标
            if (!obj_jq || "mc_new_box" === obj_jq.attr("mod_id") || !mc_filter_chip_and_recvcard_idx(obj_card_filter, i_recv, mc_get_appoint_obj(obj_jq, "chip_name").innerText)) {
                b_group_recv = false;
                continue;
            }
            // 整合卡数据
            str_intergration_key = mc_sendbox_handle_compose_data(obj_jq[0], obj_box_size, ARY_BOX_DATA, ARY_MOD_DATA, obj_integration_data, str_param, i_recv);
        }
        // 此连线下卡全部通过筛选且整合之后数据长度若加1 -> 接收卡群发 -> 更改接收卡标识为-1
        var ui_intergration_after_len = Object.keys(obj_integration_data).length;

        if (b_group_recv && ui_intergration_after_len - 1 === ui_intergration_before_len && obj_integration_data[str_intergration_key]) {
            obj_integration_data[str_intergration_key].idx = str_param + ":-1";
        }
        ui_intergration_before_len = ui_intergration_after_len;
    }
    mc_update_group_param(obj_integration_data, obj_card_cnt);
    arr_key = Object.keys(obj_integration_data);
    var arr_result = [];

    // 去除被整合项
    for (var index = 0; index < arr_key.length; index++) {
        var obj_data = obj_integration_data[arr_key[index]];

        if (obj_data) {
            if (-1 === obj_data.idx.indexOf("(")) {
                obj_data.idx = "(" + obj_data.idx + ")";
            }
            arr_result.push(obj_data);
        }
    }
    return arr_result;

    // 添加对象数据 对象，key
    function add_data(o_data, str_keys) {
        if (o_data[str_keys]) {
            o_data[str_keys] += 1;
        } else {
            o_data[str_keys] = 1;
        }
        return;
    }
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    检验更新配置信息群发口
 * 参数:
 *     @param {Promise<Object>} obj_integration_data 整合数据对象
 *     @param {Promise<Object>} obj_card_cnt 各个数据口子卡数量保存对象
 * 返回：
 *     NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.9.18
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_update_group_param(obj_integration_data, obj_card_cnt) {
    if ("[OBJECT OBJECT]" !== Object.prototype.toString.call(obj_integration_data).toUpperCase()) {
        return;
    }
    if ("[OBJECT OBJECT]" !== Object.prototype.toString.call(obj_card_cnt).toUpperCase()) {
        return;
    }
    var arr_key = Object.keys(obj_integration_data);

    if (1 === arr_key.length) {
        return;
    }
    var obj_group_data_port_cnt = {};
    var obj_group_data_hub_cnt = {};
    var obj_group_data_hubport_cnt = {};
    var obj_group_data_recv_cnt = {};

    for (var idx = 0; idx < arr_key.length; idx++) {
        var str_key = arr_key[idx];
        var obj_data_item = obj_integration_data[str_key];
        var str_param = obj_data_item.idx;

        // 只有一项索引存在且该数据下接收卡索引位置为"-1"
        if (1 === str_param.split(",").length && "-1" === str_param.substr(str_param.lastIndexOf(":") + 1).split(")")[0]) {
            var arr_param = str_key.substr(str_key.lastIndexOf("_") + 1).split(":");


            add_data(obj_group_data_port_cnt, arr_param[0], str_key);
            add_data(obj_group_data_hub_cnt, arr_param[0] + ":" + arr_param[1], str_key);
            add_data(obj_group_data_hubport_cnt, arr_param[0] + ":" + arr_param[1] + ":" + arr_param[2], str_key);
            add_data(obj_group_data_recv_cnt, str_key, str_key);
        }
    }
    mc_display_compose_data(obj_group_data_hubport_cnt, obj_card_cnt.hubport_cnt, obj_integration_data, 3);
    mc_display_compose_data(obj_group_data_hub_cnt, obj_card_cnt.hub_cnt, obj_integration_data, 2);

    if (obj_card_cnt.b_port) {
        mc_display_compose_data(obj_group_data_port_cnt, obj_card_cnt.port, obj_integration_data, 1);
    }

    return;
    // 添加对象数据 对象，key，data
    function add_data(o_data, str_keys, data) {
        if (o_data[str_keys]) {
            o_data[str_keys].push(data);
        } else {
            o_data[str_keys] = [data];
        }
        return;
    }
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    对比数据是否相同 更新对应索引
 * 参数:
 *     @param {Promise<Object>} obj_group_data_cnt 群发数据对应卡数量对象
 *     @param {Promise<Object>} obj_card_cnt 各个数据口子卡数量保存对象
 *     @param {Promise<Object>} obj_integration_data 整合数据对象
 *     @param {Promise<Array>} ui_group_idx 匹配更改索引下标位置
 * 返回：
 *     NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.9.18
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_display_compose_data(obj_group_data_cnt, obj_card_cnt, obj_integration_data, ui_group_idx) {
    var arr_key = Object.keys(obj_group_data_cnt);

    for (var index = 0; index < arr_key.length; index++) {
        var str_same_param = arr_key[index];
        var arr_same_key = obj_group_data_cnt[str_same_param];
        var ui_same_cnt = arr_same_key.length;

        // 数量与筛选前是否匹配
        if (0 !== ui_same_cnt && ui_same_cnt === obj_card_cnt[str_same_param]) {
            var str_compose_data = arr_same_key[0].substr(0, arr_same_key[0].lastIndexOf("_"));
            var b_same_data = true;

            // 比较数据是否相同
            for (var idx = 1; idx < ui_same_cnt; idx++) {
                if (str_compose_data !== arr_same_key[idx].substr(0, arr_same_key[idx].lastIndexOf("_"))) {
                    b_same_data = false;
                    break;
                }
            }

            if (b_same_data) {
                var str_new_idx = mc_tool_switch_param_group(obj_integration_data[arr_same_key[0]].idx, ui_group_idx);

                // 删除重复数据
                while (--ui_same_cnt) {
                    obj_integration_data[arr_same_key[ui_same_cnt]] = false;
                }
                obj_integration_data[arr_same_key[0]].idx = str_new_idx;
            }
        }
    }
    return;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    箱体配置筛选数据：芯片类型和下标
 * 参数:
 *     @param {Promise<Object>} obj_card_filter 筛选数据下标、芯片信息
 *     @param {Promise<Number>} ui_idx_box 当前筛选箱体在连线中位置
 *     @param {Promise<String>} str_chip_name 当前筛选箱体芯片信息
 * 返回：
 *     @returns {Promise<Boolean>}
 *      false 当前箱体不符合筛选要求
 *      true 当前箱体符合筛选要求
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.01.06
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_filter_chip_and_recvcard_idx(obj_card_filter, ui_idx_box, str_chip_name) {
    if (obj_card_filter && "[object Object]" === Object.prototype.toString.call(obj_card_filter)) {
        var ui_receive = Number(obj_card_filter.card_order.split(":")[4]);

        // 1.compare receive card index
        if (-1 !== ui_receive) {
            if (ui_receive !== ui_idx_box) {
                return false;
            }
        }
        // 2.compare receive card type
        if (str_chip_name !== obj_card_filter.card_type) {
            return false;
        }
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取卡发送参数 卡参数处理
 * 参数:
 *     @param {Promise<String>} str_key S1_P1_H1:P1 / S1:P1
 *     @param {Promise<Boolean>} b_hardware_state 硬件连接状态
 * 返回：
 *     @returns {Promise<Object>}
 *      false 参数有误
 *      {
 *          str_param : SEND:SENDPORT:HUB:HUBPORT,
 *          str_sendport : SEND:SENDPORT
 *      }
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.29
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_card_param_handle(str_key, b_hardware_state) {
    if ("[object String]" !== Object.prototype.toString.call(str_key)) {
        return null;
    }

    var arr_card_idx = str_key.split(":");
    var arr_param = mc_get_data_param(arr_card_idx[0], 0, 1);
    // send:sendport/send:sendport:hub:hubport
    var str_param = arr_param[0];
    var str_port = Number(arr_card_idx[1].slice(1)) - 1;
    var str_sendport = "";

    if (3 === arr_param[1]) {
        if (!b_hardware_state) {
            // 无硬件连接 HUB相关置0 send:sendport:0:0
            str_sendport = str_param.substring(0, str_param.lastIndexOf(":"));
            str_param = str_sendport + ":0:0";
        } else {
            // add port
            str_sendport = str_param.substr(0, str_param.lastIndexOf(":"));
            str_param += ":" + str_port;
        }
    }

    if (1 === arr_param[1]) {
        // 发送卡端口hub、hubport 置0
        str_sendport = str_param + ":" + str_port;
        str_param = str_sendport + ":0:0";
    }
    return {
        str_param: str_param,
        str_sendport: str_sendport
    };
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    SENDPORT可群发数据处理 多余数据清除 转换请求参数 SENDPORT为-1 === 此口群发
 *    SENDPORT 为 -1 则其余参数口也为-1
 * 参数:
 *     @param {Promise<Array>} arr_card_cnt 卡数量数组 长度为发送卡数量 每项对象记录发送卡port:cnt,hub:cnt,hubp:cnt
 *     @param {Promise<Array>} arr_sendport_judge 群发PORT的SENDCARD数组 [[1],[1],,] 每项为一张发送卡 内容为1表示其PORT口群发
 *     @param {Promise<Array>} arr_same_data 数据对象 [{idx:"",data:{}},,]
 * 返回：
 *     @returns {Promise<Object>}
 *      false 参数有误
 *      arr_same_data 整合后数据 多余数据为空
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.29
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_data_transform_sendport(arr_card_cnt, arr_sendport_judge, arr_same_data) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_card_cnt)) {
        return false;
    }
    if ("[object Array]" !== Object.prototype.toString.call(arr_sendport_judge)) {
        return false;
    }
    if ("[object Array]" !== Object.prototype.toString.call(arr_same_data)) {
        return false;
    }
    for (var i = 0; i < arr_sendport_judge.length; i++) {
        if (!arr_sendport_judge[i]) {
            continue;
        }
        if (1 !== arr_sendport_judge[i][0] && 1 !== arr_sendport_judge[i].length) {
            continue;
        }
        var arr_send = arr_card_cnt[i];

        arr_same_data = transform_param(arr_send, arr_same_data);
    }

    function transform_param(ary_send, ary_same_data) {
        var obj_data = null;
        var arr_first = ary_send[0].split(":");
        // var str_new_param = "(" + arr_first[0] + ":-1:" + arr_first[2] + ":" + arr_first[3] + ":-1)";
        var str_new_param = "(" + arr_first[0] + ":-1:-1:-1:-1)";

        for (var index = 0; index < ary_send.length; index++) {
            var str_idx = "(" + ary_send[index] + ":-1)";

            for (var j = 0; j < ary_same_data.length; j++) {
                if (!ary_same_data[j].sendport) {
                    return ary_same_data;
                }
                var s_idx = ary_same_data[j].idx;

                if (str_idx === s_idx) {
                    obj_data = ary_same_data[j].data;
                    // ary_same_data[j] = "";
                    // add_index = j;
                    ary_same_data.splice(j, 1);
                    j--;
                    break;
                }
            }
        }
        // ary_same_data[add_index] = {
        //     "idx": str_new_param,
        //     "data": obj_data
        // };
        ary_same_data.push({
            "idx": str_new_param,
            "data": obj_data
        });
        return ary_same_data;
    }

    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取箱体变换数据
 * 参数:
 *     @param {Promise<Object>} obj_js js对象
 *     @param {Promise<Object>} obj_box_size 记录箱体大小对象
 *     @param {Promise<Array>} ary_box_data ARY_BOX_DATA
 *     @param {Promise<Array>} ary_mod_data ARY_MOD_DATA
 * 备注：
 *      obj_data = {
 *                  str_rotation: "(0:0:angle)",
 *                  str_mirror: "0",
 *                  str_scale: "(0:0:Xs:Ys)",
 *                  str_size: "(W:H)", // 与变换无关
 *                  str_box_name: "mc_box_0",
 *                  str_chip_name: "FPGA",
 *                  str_cut:"0,0,0,0"
 *                 }
 * 返回：
 *     @returns {Promise<Object>}
 *      false 参数有误
 *      obj_data
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.18
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_transform_data(obj_js, obj_box_size, ary_box_data, ary_mod_data) {
    if ("[object HTMLDivElement]" !== Object.prototype.toString.call(obj_js)) {
        return false;
    }
    var arr_msg = mc_analysis_transform_msg(obj_js, "all", true);
    var obj_data = new format_transform_data();
    var str_box_name = obj_js.getAttribute("mod_id");
    var str_page_size = obj_js.getAttribute("mod_wg") + ":" + obj_js.getAttribute("mod_hg") + ")";
    var str_size = "65535:65535)";

    // 图像大小与变换无关 且 若设置过图像大小 WH数据为设置数据 否则置为655*355
    // 无箱体大小数据 添加
    if (!obj_box_size[str_box_name]) {
        var arr_box_size = mc_layout_get_box_size(str_box_name, ary_box_data, ary_mod_data);

        if (arr_box_size) {
            obj_box_size[str_box_name] = "(" + arr_box_size[0] + ":" + arr_box_size[1] + ")";
        }
    }
    // 对比 若更改使用更改数据
    if (obj_box_size[str_box_name] !== "(" + str_page_size) {
        str_size = str_page_size;
    }
    obj_data.str_size = str_size;
    obj_data.str_box_name = str_box_name;
    obj_data.str_chip_name = $(obj_js).children(".mod_msg_box").children(".chip_name").text();

    if (arr_msg) {
        var ui_angle = Number(arr_msg[1]);

        // angle = 360置为0
        if (ui_angle && 360 !== ui_angle) {
            obj_data.str_rotation = "(0:0:" + ui_angle + ")";
        }
        if (arr_msg[2] && 2 === arr_msg[2].length) {
            obj_data.str_scale = "(0:0:" + arr_msg[2][0] + ":" + arr_msg[2][1] + ")";
        }
        if (arr_msg[3]) {
            obj_data.str_mirror = String(arr_msg[3]);
        }
        if (arr_msg[4]) {
            obj_data.str_cut = arr_msg[4];
            var arr_cut = arr_msg[4].split(",");

            obj_data.str_size = "(" + arr_cut[0] + ":" + arr_cut[2] + ":" + obj_data.str_size;
        }
    } else {
        obj_data.str_size = "(0:0:" + obj_data.str_size;
    }

    var str_data_key = obj_data.str_box_name + "_" + obj_data.str_chip_name + "_" + obj_data.str_rotation + "_" + obj_data.str_scale + "_" + obj_data.str_mirror + "_" + str_size;

    return [obj_data, str_data_key];
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    变换参数数据格式/箱体配置发送数据格式
 * 参数:
 *     无
 * 返回：
 *     NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.18
 *      内容 : 所有代码
 ************************************************************************************************/
function format_transform_data() {
    this.str_mirror = "0";
    this.str_rotation = "(0:0:0)";
    this.str_scale = "(0:0:1.0:1.0)";
    this.str_cut = "0,0,0,0";
    // 箱体大小(W:H)
    this.str_size = false;
    // 箱体名称
    this.str_box_name = "";
    // 芯片名称
    this.str_chip_name = "";
}

// req-----
/*eslint complexity: ["error", 30]*/
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    群发箱体基础信息
 * 参数:
 *     @param {Promise<Array>} arr_box_data 发送数据
 *     @param {Promise<Object>} obj_param_data {b_load:Boolean是否固化, str_workmode:String工作模式}
 *     @param {Promise<Object>} obj_cache_box 缓存发送数据对象
 *     @param {Promise<Function>} fn_callback 回调函数
 *     @param {Promise<boolean>} b_if_send_box_name 是否发送箱体名称 true 是 / false 否 若无箱体参数则发名称
 * 返回：
 *     @returns {Promise<Boolean>}
 *      false 参数有误
 *      true 发送数据
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.01.06
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_send_box_base(arr_box_data, obj_param_data, obj_cache_box, fn_callback, b_if_send_box_name) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_box_data)) {
        fn_callback();
        return false;
    }
    if ("[object Object]" !== Object.prototype.toString.call(obj_param_data)) {
        fn_callback();
        return false;
    }
    if ("[object Function]" !== Object.prototype.toString.call(fn_callback)) {
        fn_callback();
        return false;
    }
    var str_memtype = obj_param_data.b_load ? "FLS" : "RAM";
    var obj_req_sdk = new mc_sdk_req_mgr();
    var obj_sdk_param = new mc_sdk_param();
    var str_mirror = "0";
    var str_rotation = "(0:0:0)";
    var str_scale = "(0:0:1:1)";
    // 水平头部裁剪数值:垂直头部裁剪数值:水平像素点个数:垂直像素点个数
    var str_size = "(0:0:0:0)";
    var str_cut = "0,0,0,0";
    var str_workmode = obj_param_data.str_workmode;
    var obj_recvcard_data_list_md5 = {};

    obj_sdk_param.set_param_clear();
    obj_sdk_param.set_func("HW_BOX_BASE");
    obj_sdk_param.set_cmd("SET_PARAM");
    for (var i = 0; i < arr_box_data.length; i++) {
        var obj_data = arr_box_data[i];
        var str_param_name = String(i);

        if (obj_data) {
            var obj_transform_data = obj_data.data;
            var s_mirror = obj_transform_data.str_mirror;
            var s_rotation = obj_transform_data.str_rotation;
            var s_scale = obj_transform_data.str_scale;
            var s_size = obj_transform_data.str_size;
            var s_cut = obj_transform_data.str_cut;
            var str_box_name = obj_transform_data.str_box_name;

            str_mirror = ("string" === typeof s_mirror && 0 !== s_mirror.length) ? s_mirror : str_mirror;
            str_rotation = ("string" === typeof s_rotation && 0 !== s_rotation.length) ? s_rotation : str_rotation;
            str_scale = ("string" === typeof s_scale && 0 !== s_scale.length) ? s_scale : str_scale;
            str_size = ("string" === typeof s_size && 0 !== s_size.length) ? s_size : str_size;
            str_cut = ("string" === typeof s_cut && 0 !== s_cut.length) ? s_cut : str_cut;

            var ary_box_data = obj_cache_box.get_trans_box(str_box_name, str_mirror, str_rotation, str_scale, str_cut);
            var ARR_BOX_DATA = ary_box_data[0];
            // var g_b_lod_box_state = ary_box_data[1];
            var ui_box_idx = mc_main_get_idx_by_name(ARR_BOX_DATA, obj_transform_data.str_box_name);
            var obj_box_base = ARR_BOX_DATA[ui_box_idx].data.mc_util_get_device_data();
            var str_data_type = "";
            var str_data = "";
            //  0 < obj_box_base.get_param_cnt()
            // 由按钮控制下发

            if (!b_if_send_box_name) {
                if (0 !== obj_box_base.get_param_cnt()) {
                    str_data_type = "SEND_JSON";
                    str_data = obj_box_base.get_json();
                } else {
                    str_data_type = "BOX_FILE";
                    str_data = str_box_name;
                }
            } else {
                str_data_type = "BOX_FILE";
                str_data = str_box_name;
            }
            var str_cal_val = mc_sort_param_value(obj_box_base);
            var str_md5 = md5(str_cal_val);
            var ary_data = obj_recvcard_data_list_md5[str_md5];


            if (
                ary_data &&
                ary_data[0] === obj_transform_data.str_chip_name &&
                ary_data[2] === str_rotation &&
                ary_data[3] === str_scale &&
                ary_data[4] === str_size &&
                ary_data[5] === str_mirror &&
                ary_data[6] === str_cut
            ) {
                var str_upadta_param_val = obj_sdk_param.get_param_value(ary_data[1]);

                str_upadta_param_val = str_upadta_param_val + "," + obj_data.idx;
                obj_sdk_param.set_param_value(ary_data[1], str_upadta_param_val);
                continue;
            } else {
                // obj_recvcard_data_list_md5[str_md5] = [obj_transform_data.str_chip_name,str_param_name,str_rotation,str_scale,str_size];
                obj_recvcard_data_list_md5[str_md5] = [obj_transform_data.str_chip_name, str_param_name, str_rotation, str_scale, str_size, str_mirror, str_cut];
                // obj_recvcard_data_list_md5[str_md5] = [obj_transform_data.str_chip_name,str_param_name];
            }

            obj_sdk_param.set_param_value(str_param_name, obj_data.idx);
            obj_sdk_param.set_attr_val(str_param_name, str_data_type, str_data);
            obj_sdk_param.set_attr_val(str_param_name, "CHIPNAME", obj_transform_data.str_chip_name);
            obj_sdk_param.set_attr_val(str_param_name, "MEMTYPE", str_memtype);
            obj_sdk_param.set_attr_val(str_param_name, "MIRROR", str_mirror);
            obj_sdk_param.set_attr_val(str_param_name, "ROTATION", str_rotation);
            obj_sdk_param.set_attr_val(str_param_name, "SCALE", str_scale);
            // var ary_size = str_size.split(":");

            obj_sdk_param.set_attr_val(str_param_name, "SIZE", str_size);
            // obj_sdk_param.set_attr_val(str_param_name, "SIZE", "(" + ary_size[2] + ":" + ary_size[3]);
            obj_sdk_param.set_attr_val(str_param_name, "WORKMODE", str_workmode);
        }
    }
    // console.log(obj_sdk_param.get_json());
    obj_req_sdk.push_req(obj_sdk_param.get_json(), fn_callback);
    return true;
}

// ----------------------------------修改显示画布大小信息框-----------------------------------------
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    构建修改显示画布大小html
 * 参数:
 *     @param {Promise<Object>} obj_param
 *     @param {Promise<Function>} update_canvas_w 修改宽响应
 *     @param {Promise<Function>} update_canvas_h 修改高响应
 * 备注:
 *     var obj_create = {
 *       obj: 父元素:object,
 *       edit_w :编辑框控件对象:object,
 *       edit_h :编辑框控件对象:object,
 *       chg_w :修改宽度响应函数:function,
 *       chg_h:修改高度响应函数:function
 *     }
 * 返回：
 *     @returns {Promise<Array>}
 *      arr_return
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.10.30
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_construct_canvas_msg_html(obj_param, update_canvas_w, update_canvas_h) {
    if ("[object Object]" !== Object.prototype.toString.call(obj_param)) {
        return false;
    }
    var obj_edit_w = obj_param.edit_w;
    var obj_edit_h = obj_param.edit_h;
    var str_html = "";

    obj_edit_w.on_val_chg = update_canvas_w;
    obj_edit_w.set_type("uint");
    obj_edit_w.set_min_val("1");
    obj_edit_w.set_style_width("50px");
    obj_edit_w.set_style_height("20px");
    obj_edit_w.set_val("4096");
    str_html = obj_edit_w.get_html_txt() + "<span style='margin:0 4px;color:#fff;'>X</span>";

    obj_edit_h.on_val_chg = update_canvas_h;
    obj_edit_h.set_type("uint");
    obj_edit_h.set_min_val("1");
    obj_edit_h.set_style_width("50px");
    obj_edit_h.set_style_height("20px");
    obj_edit_h.set_val("2160");
    str_html += obj_edit_h.get_html_txt();

    obj_param.obj.innerHTML = str_html;
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    更新当前模块整体偏移宽高显示字串
 * 参数:
 *     @param {Promise<Array>} arr_msg 最新模块边界信息 [minx,miny,maxx,maxy]真实大小
 *     @param {Promise<Boolean>} b_update_bgsize 是否更新背景大小 定位、快速布局、变换模块、粘贴模块时更新
 *     @param {Promise<Boolean>} b_update_scale 是否进行画布缩放（添加模块后，若当前添加内容无法完全显示，进行画布缩放）
 * 返回：
 *     @returns {Promise<Boolean>}
 *      str_msg 设置成功 前模块整体偏移
 *      false 参数错误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.8
 *      内容 : 所有代码
 ************************************************************************************************/
function update_module_msg_txt(arr_msg, b_update_bgsize, b_update_scale) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_msg) || 4 !== arr_msg.length) {
        return false;
    }
    var ui_grid_w = Number(document.getElementById("mod_box_next").getAttribute("grid_w"));
    var arr_title = ["L:", "T:", "W:", "H:"];
    var str_msg = "";
    // 计算更新画布大小
    var obj_update_bgsize = {};

    for (var i = 0; i < arr_msg.length; i++) {
        var str_type = arr_title[i];
        var ui_num = Math.round(Number(arr_msg[i]) / ui_grid_w);

        str_msg += ui_num + ":";
        obj_update_bgsize[str_type] = ui_num;
    }
    str_msg = str_msg.substr(0, str_msg.lastIndexOf(":"));
    str_msg = str_msg.trim();
    document.getElementsByClassName("mc_module_msg")[0].innerText = str_msg;
    if (b_update_bgsize) {
        // 更新画布大小
        mc_adapt_canvasbg_size(obj_update_bgsize[arr_title[0]] + obj_update_bgsize[arr_title[2]], obj_update_bgsize[arr_title[1]] + obj_update_bgsize[arr_title[3]]);
    }

    // 更新画布缩放
    if (b_update_scale) {
        mc_add_module_set_canvas_scale(Number(arr_msg[2]), Number(arr_msg[3]));
    }
    return str_msg;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    添加模块后，若当前操作内容无法完全显示，进行画布缩放
 * 参数:
 *     @param {Promise<Number>} ui_w 模块整体宽度 实际值
 *     @param {Promise<Number>} ui_h 模块整体高度
 * 返回：
 *     @returns {Promise<Boolean>}
 *      true 设置成功
 *      false 参数错误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.06.09
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_add_module_set_canvas_scale(ui_w, ui_h) {
    if ("[object Number]" !== Object.prototype.toString.call(ui_w) || "[object Number]" !== Object.prototype.toString.call(ui_h)) {
        return false;
    }
    var obj_box = document.getElementById("mod_box_next");
    var ui_scale_multiple = get_box_scale_multiple();
    var ui_module_w = Number(ui_w) * (ui_scale_multiple / 100);
    var ui_module_h = Number(ui_h) * (ui_scale_multiple / 100);
    var ui_box_w = obj_box.offsetWidth;
    var ui_box_h = obj_box.offsetHeight;
    var ui_dval_w = ui_module_w - ui_box_w;
    var ui_dval_h = ui_module_h - ui_box_h;

    // 超出显示区域
    if (0 < ui_dval_w || 0 < ui_dval_h) {
        if (0 <= ui_dval_w - ui_dval_h) {
            var u_module_w = ui_module_w;


            while (u_module_w > ui_box_w) {
                // ui_box_scale_step 缩放步进
                ui_scale_multiple -= ui_box_scale_step;
                u_module_w = Number(ui_w) * (ui_scale_multiple / 100);
            }
        } else {
            var u_module_h = ui_module_h;

            while (u_module_h > ui_box_h) {
                ui_scale_multiple -= ui_box_scale_step;
                u_module_h = Number(ui_h) * (ui_scale_multiple / 100);
            }
        }
        mc_scale_set(false, false, ui_scale_multiple);
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    比较更新模块整体显示大小
 * 参数:
 *     @param {Promise<Array>} arr_unselect_size 未选中模块Lmin,Tmin,Lmax+Wr,Lmax+Hr
 *     @param {Promise<Array>} arr_select_size 选中模块 Lmin,Tmin,Lmax+Wr,Lmax+Hr
 * 返回：
 *     @returns {Promise<Boolean>}
 *      true 设置成功
 *      false 参数错误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.10
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_compare_update_module_msg_txt(arr_unselect_size, arr_select_size) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_select_size)) {
        return false;
    }
    var arr_msg = [];
    var ui_select_l = arr_select_size[0];
    var ui_select_t = arr_select_size[1];
    var ui_select_maxl = arr_select_size[2];
    var ui_select_maxt = arr_select_size[3];

    arr_msg.push(ui_select_l, ui_select_t, ui_select_maxl - ui_select_l, ui_select_maxt - ui_select_t);
    if (arr_unselect_size) {
        // 对比数据
        var ui_unselect_l = arr_unselect_size[0];
        var ui_unselect_t = arr_unselect_size[1];
        var ui_unselect_maxl = arr_unselect_size[2];
        var ui_unselect_maxt = arr_unselect_size[3];

        if (ui_unselect_l < ui_select_l) {
            arr_msg[0] = ui_unselect_l;
        }
        if (ui_unselect_t < ui_select_t) {
            arr_msg[1] = ui_unselect_t;
        }
        var compare_w1 = ui_unselect_maxl - arr_msg[0];
        var compare_w2 = ui_select_maxl - arr_msg[0];
        var compare_h1 = ui_unselect_maxt - arr_msg[1];
        var compare_h2 = ui_select_maxt - arr_msg[1];

        if (compare_w1 < compare_w2) {
            arr_msg[2] = compare_w2;
        } else {
            arr_msg[2] = compare_w1;
        }
        if (compare_h1 < compare_h2) {
            arr_msg[3] = compare_h2;
        } else {
            arr_msg[3] = compare_h1;
        }
    }
    update_module_msg_txt(arr_msg);
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取当前整体模块显示信息字串
 * 参数:
 *     无
 * 返回：
 *     @returns {Promise<Boolean>}
 *      module size msg: string
 *      false 参数错误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.14
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_module_size_msg() {
    var obj_msg = document.getElementsByClassName("mc_module_msg");

    if (obj_msg && 0 !== obj_msg.length) {
        return obj_msg[0].innerText;
    }
    return false;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取当前适应模块大小画布大小
 * 参数:
 *     @param {Promise<String>} str_module_msg 当前模块整体显示信息 "L:0 T:0 W:0 H:0"
 * 返回：
 *     @returns {Promise<Boolean>}
 *      [String,false] 设置成功 String设置数值 false无需设置
 *      false 参数错误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.01.27
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_adapt_canvasbg_size(str_module_msg) {
    if ("string" !== typeof str_module_msg || 0 === str_module_msg.length) {
        return false;
    }
    var str_w = "4096";
    var str_h = "2160";

    if (str_module_msg) {
        var arr_module_msg = str_module_msg.split(" ");

        if (arr_module_msg && 4 === arr_module_msg.length) {
            var str_width = arr_module_msg[2];
            var str_height = arr_module_msg[3];

            if (-1 !== str_width.indexOf("W")) {
                str_w = str_width.split(":")[1];
            }
            if (-1 !== str_height.indexOf("H")) {
                str_h = str_height.split(":")[1];
            }
            if (4096 > Number(str_w)) {
                // str_w = false;
                str_w = "4096";
            } else {
                str_w = String(Number(str_w) + 100);
            }
            if (2160 > Number(str_h)) {
                // str_h = false;
                str_h = "2160";
            } else {
                str_h = String(Number(str_h) + 100);
            }
        }
    }
    return [str_w, str_h];
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    回撤重做 更新整体信息
 * 参数:
 *     @param {Promise<String>} str_msg 模块整体信息
 * 返回：
 *     @returns {Promise<Boolean>}
 *      true 设置成功
 *      false 参数错误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.01.19
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_operate_update_module_msg(str_msg) {
    if ("[object String]" !== Object.prototype.toString.call(str_msg)) {
        return false;
    }
    document.getElementsByClassName("mc_module_msg")[0].innerText = str_msg;
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    更新当前模块数量
 * 参数:
 *     无
 * 返回：
 *     @returns {Promise<Boolean>}
 *      true 设置成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.01.19
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_update_module_size() {
    var obj_size = document.getElementsByClassName("mc_module_size");
    var mod_list = document.getElementsByClassName("mc_mod");

    if (obj_size && 0 !== obj_size.length) {
        obj_size[0].innerText = " " + mod_list.length;
    }
    return true;
}

// -------------------------------------------其他------------------------------------------------
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    更新索引对应标识处为'-1' 表群发
 *    "0:0:0:0:0" -> "0:0:0:-1:0"
 * 参数:
 *     @param {Promise<String>} str_param 待更新字串
 *     @param {Promise<Number>} ui_idx 更新索引下标
 * 返回：
 *     @returns {Promise<String>}
 *      更新索引字串
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.9.18
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_tool_switch_param_group(str_param, ui_idx) {
    if ("[OBJECT STRING]" !== Object.prototype.toString.call(str_param).toUpperCase()) {
        return str_param;
    }
    if ("[OBJECT NUMBER]" !== Object.prototype.toString.call(ui_idx).toUpperCase()) {
        return str_param;
    }
    var arr_param = str_param.split(":");

    arr_param.splice(ui_idx, 1, -1);
    return arr_param.join(":");
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    大屏连接 ---设置发送卡、hub卡以及对应的port项 显示隐藏
 * 参数:
 *     @param {Promise<Object>} obj_msg
 * 备注:
 *       obj_setcard_hub_show = {
 *           obj_hub: obj_hub, HUB选项对象
 *           b_show: b_show 是否显示
 *     }
 * 返回：
 *     @returns {Promise<Boolean>}
 *      true 设置成功
 *      false 参数有误
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.10.21
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_setcard_display_hub(obj_msg) {
    if ("[object Object]" !== Object.prototype.toString.call(obj_msg) || "[object HTMLDivElement]" !== Object.prototype.toString.call(obj_msg.obj_hub)) {
        return false;
    }
    var str_show = obj_msg.str_show;

    if ("1" === str_show) {
        obj_msg.obj_hub.style.display = "block";
    }
    if ("0" === str_show) {
        obj_msg.obj_hub.style.display = "none";
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    设置卡时检验此PORT口是否可设置当前参数
 * 参数:
 *     @param {Promise<Object>} obj_same_hub_queue 参数hub值队列
 *     @param {Promise<Array>} arr_select 选中元素
 *     @param {Promise<String>} str_idx 当前设置
 * 备注:
 *     同个口下若接接收卡 不允许接HUB卡 相反同理
 *     检验可接卡条件：此口下还未接口/此口下接的卡与当前设置卡类型相同/此口下卡被全选
 * 返回：
 *     @returns {Promise<Object>}
 *      false 参数设置/不可设置
 *      true 可创建
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.10
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_setcard_check_port(obj_same_hub_queue, arr_select, str_idx) {
    if ("object" !== typeof obj_same_hub_queue) {
        return false;
    }
    if ((!Array.isArray(arr_select)) || 0 === arr_select.length) {
        return false;
    }
    if ("string" !== typeof str_idx || 0 === str_idx.length) {
        return false;
    }
    var arr_key = Object.keys(obj_same_hub_queue);

    if (0 !== arr_key.length) {
        for (var idx_key = 0; idx_key < arr_key.length; idx_key++) {
            var s_key = arr_key[idx_key];

            if (0 === obj_same_hub_queue[s_key].length) {
                continue;
            }

            // EP:S0_P0_H0/ S0_P0
            var ary_key = s_key.split(":");
            var str_key = ary_key[0];

            // 新设置卡口存在于之前设置
            if (str_key === str_idx) {
                return true;
            }

            var arr_type_len = str_idx.split("_");
            var arr_key_type_len = str_key.split("_");

            // EP:S0
            if (1 === arr_key_type_len.length) {
                // EP:S0_P0
                str_key = ary_key.join("_");
                arr_key_type_len = str_key.split("_");
            }

            // 同类型卡不比较
            if (arr_type_len.length === arr_key_type_len.length) {
                continue;
            }

            // S0_P0_H0 -> S0_P0
            if (str_idx.substr(0, str_key.length) === str_key || str_key.substr(0, str_idx.length) === str_idx) {
                // 检测当前设置队列冲突口是否被全部选中
                var b_set = check_select(obj_same_hub_queue[s_key], arr_select);

                // 检测当前设置队列冲突口下卡长度
                if (b_set && 2 === arr_type_len.length) {
                    var ui_recvcard_len = mc_get_card_len(obj_same_hub_queue, str_idx);

                    if (ui_recvcard_len > arr_select.length) {
                        return false;
                    }
                }
                return b_set;
            }
        }
    }

    // 选中元素是否为当前不可设置元素 true可设置
    function check_select(arr_list, arr_selected) {
        // 手动连线设置卡
        if (1 === arr_select.length && false === arr_select[0]) {
            return false;
        }
        if (arr_list.length > arr_selected.length) {
            return false;
        }
        var ui_cnt = 0;

        for (var idx = 0; idx < arr_list.length; idx++) {
            for (var index = 0; index < arr_selected.length; index++) {
                if (arr_selected[index][0] === arr_list[idx][0]) {
                    ui_cnt++;
                    break;
                }
            }
        }
        if (ui_cnt === arr_list.length) {
            return true;
        }
        return false;
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取卡口下连接卡数量
 * 参数:
 *     @param {Promise<Object>} obj_same_hub_queue 参数hub值队列
 *     @param {Promise<String>} str_idx 卡口 S0_P0
 * 返回：
 *     @returns {Promise<Number>}
 *      false 参数有误
 *      ui_len 接收卡数量
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.01.14
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_card_len(obj_same_hub_queue, str_idx) {
    if ("object" !== typeof obj_same_hub_queue) {
        return false;
    }
    if ("string" !== typeof str_idx || 0 === str_idx.length) {
        return false;
    }
    var arr_key = Object.keys(obj_same_hub_queue);
    var ui_len = 0;

    for (var i = 0; i < arr_key.length; i++) {
        var str_key = arr_key[i];
        var str_keys = str_key.split(":").join("_");
        var idx_len = str_idx.length;

        if (str_key.substr(0, idx_len) === str_idx || str_keys.substr(0, idx_len) === str_idx) {
            ui_len += obj_same_hub_queue[str_key].length;
        }
    }
    return ui_len;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取当前大屏宽高箱体个数
 * 参数:
 *     @param {Promise<Object>} obj_same_hub_queue 参数hub值队列
 * 返回：
 *     @returns {Promise<Array>}
 *      false 参数有误
 *      [ui_w,ui_h,ui_cnt];
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.9.14
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_screen_size(obj_same_hub_queue) {
    if ("object" !== typeof obj_same_hub_queue) {
        return false;
    }
    var arr_key = Object.keys(obj_same_hub_queue);


    if (0 !== arr_key.length) {
        var ui_min_l = Math.pow(2, 32);
        var ui_max_l = 0;
        var ui_min_t = Math.pow(2, 32);
        var ui_max_t = 0;
        var ui_cnt = 0;
        var obj_max_l = null;
        var obj_max_t = null;

        for (var idx_key = 0; idx_key < arr_key.length; idx_key++) {
            var arr_box = obj_same_hub_queue[arr_key[idx_key]];

            for (var idx = 0; idx < arr_box.length; idx++) {
                var obj_box = arr_box[idx][0];
                var ui_l = obj_box.offsetLeft;
                var ui_t = obj_box.offsetTop;

                if (ui_min_l > ui_l) {
                    ui_min_l = ui_l;
                    obj_max_l = obj_box;
                }
                if (ui_max_l < ui_l) {
                    ui_max_l = ui_l;
                    obj_max_l = obj_box;
                }
                if (ui_min_t > ui_t) {
                    ui_min_t = ui_t;
                    obj_max_t = obj_box;
                }
                if (ui_max_t < ui_t) {
                    ui_max_t = ui_t;
                    obj_max_t = obj_box;
                }
                ui_cnt++;
            }
        }
        var ui_w = ui_max_l + obj_max_l.offsetWidth - ui_min_l;
        var ui_h = ui_max_t + obj_max_t.offsetHeight - ui_min_t;

        return [ui_w, ui_h, ui_cnt];
    }
    return false;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取一组连线矩形围成的区域
 * 参数:
 *    @param { Promise<Array> } arr 一组连线对象
 * 返回:
 *    @returns { Promise<Object> } 该外围区域的 X,Y,W,H || false
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-09-16
 *       内容 : 所有代码
 ************************************************************************************************/
function get_grp_rect(arr) {
    if ("[object Array]" !== Object.prototype.toString.call(arr)) {
        return false;
    }
    var len = arr.length;
    var b_first = false;

    var min_x = null;
    var min_y = null;

    var max_x = null;
    var max_y = null;

    var cui_reg_int = /[\d.]+/g;

    for (var idx = 0; idx < len; idx++) {
        var item = arr[idx];

        if (0 !== item.length) {
            var obj = item[0];
            var msg = mc_get_child_pot_size(obj);
            // var size = get_mod_chi_obj(obj.children[0].children, "mod_size");
            // var pos = get_mod_chi_obj(obj.children[0].children, "mod_pot");
            var size = msg.str_size;
            var pos = msg.str_pot;

            if (size && pos) {
                // size = size.innerText.trim();
                // pos = pos.innerText.trim();
                size = size.trim();
                pos = pos.trim();

                var ui_x = Number(pos.match(cui_reg_int)[0]);
                var ui_y = Number(pos.match(cui_reg_int)[1]);
                var ui_w = Number(size.match(cui_reg_int)[0]);
                var ui_h = Number(size.match(cui_reg_int)[1]);

                if (b_first) {
                    // change min && max value
                    // set min
                    if (ui_x < min_x) {
                        min_x = ui_x;
                    }

                    if (ui_y < min_y) {
                        min_y = ui_y;
                    }

                    // set  max
                    var item_right_border = ui_x + ui_w;

                    if (max_x < item_right_border) {
                        max_x = item_right_border;
                    }

                    var item_bottom_border = ui_y + ui_h;

                    if (max_y < item_bottom_border) {
                        max_y = item_bottom_border;
                    }
                } else {
                    // init min x y
                    b_first = true;

                    min_x = ui_x;
                    min_y = ui_y;

                    max_x = ui_x + ui_w;
                    max_y = ui_y + ui_h;
                }
            }
        }
    }

    return {
        X: min_x,
        Y: min_y,
        W: max_x - min_x,
        H: max_y - min_y
    };
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取所有进度条并渲染页面
 * 参数:
 *    @param { Promise<Object> } obj_queue 连线的数据对象
 *    @param { Promise<Object> } hub_callback 渲染hub卡的数据回调
 *    @param { Promise<Object> } send_callback 渲染send卡的数据回调
 * 返回:
 *    @returns { Promise<Object> } html === 渲染的html字符串 && obj_max_p.val === 最大进度值; false === 参数错误;
 * 例子:
 *    NA
 * 备注:
 *    返回 html === "" && obj_max_p.val === 0 表示暂无数据;
 *    回调参数(b_err,obj_res); b_err === 读取数据的时候是否报错; obj_res 返回渲染数据；
 *    defined card type; 1 === hub card && 0 === send card
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-09-16
 *       内容 : 所有代码
 ************************************************************************************************/
function get_progress_and_render(obj_queue, hub_callback, send_callback) {
    if ("[object Object]" !== Object.prototype.toString.call(obj_queue)) {
        return false;
    }

    if ("function" !== typeof hub_callback || "function" !== typeof send_callback) {
        return false;
    }

    var queue_key = Object.keys(obj_queue);
    var ui_que_key_len = queue_key.length;

    // max progress object
    var obj_max_p = {
        val: 0,
        color: ""
    };


    if (0 === ui_que_key_len) {
        hub_callback(false, construct_return_obj(""));
        send_callback(false, construct_return_obj(""));
        return true;
    }


    // defined card type obj
    var obj_card_load_data = {
        "SEND_CARD": {
            str_card_name_default: str_sendcard_first_name,
            str_card_name_req: "SENDCARD_LIST",
            ui_req_load_type: 0,
            obj_format_data: new format_card_output_load()
        },
        "HUB_CARD": {
            str_card_name_default: str_hubcard_first_name,
            str_card_name_req: "HUBCARD_LIST",
            ui_req_load_type: 1,
            obj_format_data: new format_card_output_load()
        }
    };

    // deal and do it
    construct_grp_card_request_data();
    queue_key = sort_queue_keys();
    request_to_sdk();


    // add one grp hub card or send card request data
    function construct_grp_card_request_data() {
        for (var idx = 0; idx < ui_que_key_len; idx++) {
            var key = queue_key[idx];
            var arr = obj_queue[key];

            if (arr && 0 !== arr.length) {
                var obj_res_rect = get_grp_rect(arr);

                if (obj_res_rect) {
                    var arr_res = mc_get_data_param(key.split(":")[0], 0, 1);
                    var pos_val = "";

                    if (arr_res) {
                        pos_val = arr_res[0];

                        if (1 < arr_res[1]) {
                            // this is hub card
                            obj_card_load_data.HUB_CARD.obj_format_data.set_obj_param(key, pos_val, obj_res_rect.W.toString(), obj_res_rect.H.toString());
                            continue;
                        }
                        // this is send card
                        obj_card_load_data.SEND_CARD.obj_format_data.set_obj_param(key, pos_val, obj_res_rect.W.toString(), obj_res_rect.H.toString());
                    }
                }
            }
        }
    }

    // 获取加载负荷 并处理数据
    function request_to_sdk() {
        var arr_card = Object.keys(obj_card_load_data);

        for (var ui_i = 0; arr_card.length > ui_i; ui_i++) {
            var str_key_val = arr_card[ui_i];
            var item = obj_card_load_data[str_key_val];

            // judge data is effective data
            if (item.obj_format_data.has_param()) {
                if ("" === item.str_card_name_default.trim()) {
                    get_card_name(item);
                } else {
                    mc_get_card_outport_load(item.ui_req_load_type, item.str_card_name_default, item.obj_format_data, get_load_req_callback);
                }
            } else {
                if ("SEND_CARD" === str_key_val) {
                    send_callback(false, construct_return_obj(""));
                } else {
                    hub_callback(false, construct_return_obj(""));
                }
            }
        }
    }

    // 处理获取图像信息返回结果数据
    function deal_get_card_load_result(keys, res) {
        var obj_sdk_param = new mc_sdk_param();

        obj_sdk_param.set_json(res);

        var str_html = "";
        // defined card type; 1 === hub card && 0 === send card
        var ui_card_type = null;

        for (var hub_i = 0; hub_i < keys.length; hub_i++) {
            var str_key = keys[hub_i];
            var str_per = obj_sdk_param.get_param_value(str_key);

            if (str_per) {
                var res_name = mc_get_data_param(str_key.split(":")[0], 0, 1);

                if (res_name) {
                    if (1 < res_name[1]) {
                        ui_card_type = 1;
                    } else {
                        ui_card_type = 0;
                    }
                }

                var ui_per = Number(str_per);
                var str_color = get_progress_color(ui_per);

                // change max percent value
                if (ui_per > obj_max_p.val) {
                    obj_max_p.val = ui_per;
                    obj_max_p.color = str_color;
                }

                str_html += get_progress_bar_html(str_key, ui_per, str_color);
            }
        }

        return {
            type: ui_card_type,
            html: construct_return_obj(str_html)
        };
    }

    // get card regist name
    function get_card_name(obj) {
        mc_get_req_card_list(obj.str_card_name_req, function (str_res_name) {
            if (str_res_name) {
                mc_get_card_outport_load(obj.ui_req_load_type, str_res_name, obj.obj_format_data, get_load_req_callback);
            } else {
                // can not get card name
                hub_callback(true);
                send_callback(true);
            }
        });
    }

    // deal load request callback
    function get_load_req_callback(err, str_load) {
        if (!err) {
            var res_deal = deal_get_card_load_result(queue_key, str_load);

            if (res_deal.type) {
                hub_callback(err, res_deal.html);
            } else {
                send_callback(err, res_deal.html);
            }
            return;
        }
        hub_callback(err, str_load);
        send_callback(err, str_load);
    }

    // construct get_progress_and_render  function callback return data
    function construct_return_obj(html) {
        return {
            html: html,
            max_p: obj_max_p
        };
    }

    // sort keys
    function sort_queue_keys() {
        var obj_card_s = obj_card_load_data.SEND_CARD.obj_format_data.get_param_obj();
        var arr_k_s = Object.keys(obj_card_s);
        var arr_sort_s = arr_k_s.sort(sort_keys_fun);

        var obj_card_h = obj_card_load_data.HUB_CARD.obj_format_data.get_param_obj();
        var arr_k_h = Object.keys(obj_card_h);
        var arr_sort_h = arr_k_h.sort(sort_keys_fun);

        function sort_keys_fun(pre, last) {
            if (!pre || !last) {
                return 0;
            }

            pre = mc_replace_line_key_letters(pre);
            last = mc_replace_line_key_letters(last);

            var arr_pre = pre.split(":");
            var arr_last = last.split(":");
            var ui_len = arr_pre.length;

            for (var ui_i_sort = 0; ui_i_sort < ui_len; ui_i_sort++) {
                var ui_pre = Number(arr_pre[ui_i_sort]);
                var ui_last = Number(arr_last[ui_i_sort]);

                if (ui_pre === ui_last) {
                    continue;
                }

                if (ui_pre < ui_last) {
                    return -1;
                }

                return 1;
            }

            return 0;
        }

        var arr_sort_res = arr_sort_s.concat(arr_sort_h);

        return arr_sort_res;
    }

    return true;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    替换字母 - 连线key将字母去掉
 * 参数:
 *    @param { Promise<String> } str 连线key
 * 返回:
 *    @returns { Promise<String> } 返回去掉字母的字符串; 中间用":" 分割; || 返回原参数
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-12-22
 *       内容 : 所有代码
 ************************************************************************************************/
function mc_replace_line_key_letters(str) {
    if ("string" !== typeof str) {
        return str;
    }

    var str_res = str;

    if (str.trim()) {
        str_res = str_res.replace(/_/g, ":");
        str_res = str_res.replace(/S/g, "");
        str_res = str_res.replace(/P/g, "");
        str_res = str_res.replace(/H/g, "");
        return str_res;
    }

    return str;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取模组dom对象集合内的指定子对象
 * 参数:
 *    @param { Promise<Object> } arr_sub_obj 模组块内的所有子集对象
 *    @param { Promise<String> } class_name 需要获取的子集类名
 * 返回:
 *    @returns { Promise<Object> } 指定对象
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-1-8
 *       内容 : 所有代码
 ************************************************************************************************/
function get_mod_chi_obj(arr_sub_obj, class_name) {
    for (var idx = 0; idx < arr_sub_obj.length; idx++) {
        var obj_item = arr_sub_obj[idx];

        if (obj_item) {
            var arr_class = obj_item.classList;

            // if (arr_sub_obj[idx].className === class_name) {
            if (-1 !== JSON.stringify(arr_class).indexOf(JSON.stringify(class_name))) {
                return arr_sub_obj[idx];
            }
        }
    }
    return false;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取控件组数据
 * 参数:
 *    @param { Promise<String> } str_json 按钮组字串
 * 返回:
 *    @returns { Promise<Object> } 指定数据指定格式对象
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-1-8
 *       内容 : 所有代码
 ************************************************************************************************/
function get_item_grp_data(str_json) {
    var obj_return_data = {};
    var obj_param_rsp = new mc_sdk_param();

    obj_param_rsp.set_json(str_json);
    var ui_cnt = obj_param_rsp.get_param_cnt();

    for (var item_idx = 0; item_idx < ui_cnt; item_idx++) {
        var str_param_name = obj_param_rsp.get_param_name(item_idx);
        var str_param_value = obj_param_rsp.get_param_value(str_param_name);
        var str_attr_value = obj_param_rsp.get_attr_val(str_param_name, "ARRAY");
        // 构造value值对象
        var obj_re_value = {};

        obj_re_value.val = str_param_value;
        obj_re_value.arr = {};
        if ("undefined" !== typeof str_attr_value) {
            obj_re_value.arr = format_str_to_obj(str_attr_value);
        }
        obj_return_data[str_param_name] = obj_re_value;
    }
    return obj_return_data;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    将有键值对的字符换数据格式改为对象键值对格式
 * 参数:
 *    @param { Promise<String> } str
 * 返回:
 *    @returns { Promise<Object> } obj_data
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-1-8
 *       内容 : 所有代码
 ************************************************************************************************/
function format_str_to_obj(str) {
    if ("string" !== typeof str) {
        return false;
    }
    var obj_data = {};

    if (-1 !== str.indexOf(",")) {
        var arr_str_split = str.split(",");

        for (var idx = 0; idx < arr_str_split.length; idx++) {
            var str_gp = arr_str_split[idx];

            if (-1 !== str_gp.indexOf("=")) {
                var obj_key = str_gp.split("=")[0].trim();
                var obj_val = str_gp.split("=")[1].trim();

                obj_data[obj_key] = obj_val;
            }
        }
        return obj_data;
    }

    return false;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取dom对象的数据
 * 参数:
 *    @param { Promise<Object> } obj_div div dom对象;
 * 返回:
 *    @returns { Promise<Object> } 该对象的id,中心点top,left值
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-1-8
 *       内容 : 所有代码
 *    2. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-11-27
 *       内容 : 获取的位置值为读取样式值(优化性能)
 ************************************************************************************************/
function get_div_data(obj_div) {
    if (!mc_util_is_object_dom(obj_div)) {
        return false;
    }

    // 外接图像信息_旋转角度_缩放XY_镜像
    var arr_msg = mc_analysis_transform_msg(obj_div);

    var box_width = 0;
    var box_height = 0;
    var box_top = Number((obj_div.style.top).split("px")[0]);
    var box_left = Number((obj_div.style.left).split("px")[0]);

    if (arr_msg) {
        box_width = Number(arr_msg[0]);
        box_height = Number(arr_msg[1]);
        box_left -= Number(arr_msg[2]);
        box_top -= Number(arr_msg[3]);
    } else {
        box_width = Number((obj_div.style.width).split("px")[0]);
        box_height = Number((obj_div.style.height).split("px")[0]);
    }

    // var box_center_top = (box_height / 2) + box_top;
    // var box_center_left = (box_width / 2) + box_left;

    return {
        id: obj_div.id,
        top: (box_height / 2) + box_top,
        left: (box_width / 2) + box_left
    };
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    是否允许添加模块判断
 * 参数:
 *    @param { Promise<Boolean> } b_add_screen 是否再大屏连接页
 * 返回:
 *    @returns { Promise<Boolean> }
 *      ture 可添加
 *      false 参数有误/不可添加
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 陈小荟
 *       时间 : 2020.10.26
 *       内容 : 所有代码
 ************************************************************************************************/
function mc_judge_add_moudle(b_add_screen) {
    if ("[object Boolean]" !== Object.prototype.toString.call(b_add_screen)) {
        return false;
    }
    if (!b_add_screen) {
        var str_mod_name = mc_get_top_data("SELECT_MOD_NAME");

        if ("string" !== typeof str_mod_name || 0 >= str_mod_name.length) {
            mc_get_top_fun("mc_alert_popout", "MC_LANG_POPOUT_NO_SELECTED_MOD");
            return false;
        }
    }
    return true;
}


// ********************************************************************* 线条相关操作(创建, 更新) ********************************************************************* //
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    构造直线svg
 * 参数:
 *    @param { Promise<String> } line_len 线条长度
 *    @param { Promise<String> } line_id 线条id
 * 返回:
 *    @returns { Promise<String> } 返回线条html
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-1-8
 *       内容 : 所有代码
 ************************************************************************************************/
function construct_straight_line(line_len, line_id) {
    // 箭头数据
    var path_d = "M0,1 L0,7 L8,4 z";

    // 箭头大小
    var arrow_width = 15;
    var arrow_height = 20;

    var marker_col = "green";
    var line_col = "green";

    // 整个线条的整体高度
    var line_height = 10;
    var x1 = 0;
    var y1 = line_height;
    var x2 = line_len - arrow_width;
    var y2 = line_height;

    var svg_width = "100%";
    var svg_heignt = arrow_height;
    var str_marker_id = "arrow_marker_" + line_id;

    var str_marker = "<marker id='" + str_marker_id + "' markerUnits='strokeWidth' markerWidth='10' markerHeight='10' refX='0' refY='4' orient='auto'><path d='" +
        path_d + "' style='fill:" + marker_col + "' /></marker>";


    var str_svg = "<svg width=" + svg_width + " height=" + svg_heignt +
        " version='1.1' xmlns='http://www.w3.org/2000/svg'><defs>" + str_marker + "</defs><line x1=" + x1 + " y1=" +
        y1 + " x2=" + x2 + " y2=" + y2 +
        " stroke=" + line_col + " stroke-width='2' marker-end='url(#" + str_marker_id + ")' /></svg>";

    return str_svg;
}

// **************************************** 创建线条, 更新连线 **************************************** //
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    构造线条id;
 * 参数:
 *    @param { Promise<Object> } obj_start 开始块对象; 带id属性;
 *    @param { Promise<Object> } obj_end 结束块对象; 带id属性
 * 返回:
 *    @returns { Promise<String> } 连线id || false
 * 例子:
 *    NA
 * 备注:
 *    以上参数对象并不一定为dom对象; 只要时带id属性值对象即可,并且id值为字符串；
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2021-02-04
 *       内容 : 所有代码
************************************************************************************************/
function mc_constrct_line_id(obj_start, obj_end) {
    if (obj_start && obj_end) {
        if ("string" === typeof obj_start.id && "string" === typeof obj_end.id && obj_start.id.trim() && obj_end.id.trim()) {
            return obj_start.id.trim() + "_" + obj_end.id.trim();
        }
    }
    return false;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    创建线条dom对象
 * 参数:
 *    @param { Promise<String> } str_line_id 线条id
 *    @param { Promise<Number> } x1 开始点x坐标
 *    @param { Promise<Number> } y1 开始点y坐标
 *    @param { Promise<Number> } x2 结束点x坐标
 *    @param { Promise<Number> } y2 结束点y坐标
 *    @param { Promise<String> } str_class 添加的线条类
 * 返回:
 *    @returns { Promise<Object> } {} 返回线条和箭头的dom对象  { svg_line: 线条对象; svg_marker: 箭头对象 }
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-11-25
 *       内容 : 所有代码
 ************************************************************************************************/
function mc_construct_line(str_line_id, x1, y1, x2, y2, str_class) {
    if (!str_line_id) {
        return false;
    }

    var str_marker_id = "arrow_marker_" + str_line_id;

    // marker
    var marker_col = "green";
    var line_col = "green";

    // line
    var obj_svg_line = document.createElementNS("http://www.w3.org/2000/svg", "line");

    obj_svg_line.setAttribute("id", str_line_id);

    var str_def_class = " mod_hub_Line ";

    if ("string" === typeof str_class) {
        str_def_class += str_class;
    }
    obj_svg_line.setAttribute("class", str_def_class);


    obj_svg_line.setAttribute("x1", x1);
    obj_svg_line.setAttribute("y1", y1);

    obj_svg_line.setAttribute("x2", x2);
    obj_svg_line.setAttribute("y2", y2);

    obj_svg_line.setAttribute("stroke", line_col);
    obj_svg_line.setAttribute("stroke-width", "16");

    obj_svg_line.setAttribute("marker-end", "url(#" + str_marker_id + ")");

    var obj_marker_res = mc_construct_marker(str_marker_id, marker_col);

    // use clone node
    // var obj_marker_res = obj_marker_node.cloneNode(true);
    // obj_marker_res.setAttribute("id", str_marker_id );

    // obj_svg.appendChild(obj_marker_res);
    // obj_svg.appendChild(obj_svg_line);

    return {
        svg_line: obj_svg_line,
        svg_marker: obj_marker_res
    };
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    创建箭头dom对象
 * 参数:
 *    @param { Promise<String> } str_marker_id 箭头id
 *    @param { Promise<String> } marker_col 箭头颜色
 * 返回:
 *    @returns { Promise<Object> } 生成的箭头dom对象
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-11-25
 *       内容 : 所有代码
 ************************************************************************************************/
function mc_construct_marker(str_marker_id, marker_col) {
    if ("string" !== typeof str_marker_id) {
        return {};
    }

    var obj_svg_marker = document.createElementNS("http://www.w3.org/2000/svg", "marker");

    obj_svg_marker.setAttribute("id", str_marker_id);
    obj_svg_marker.setAttribute("stroke-width", "2");

    obj_svg_marker.setAttribute("orient", "auto");
    obj_svg_marker.setAttribute("markerUnits", "strokeWidth");

    obj_svg_marker.setAttribute("markerWidth", "10");
    obj_svg_marker.setAttribute("markerHeight", "10");

    obj_svg_marker.setAttribute("refX", "6");
    obj_svg_marker.setAttribute("refY", "4");

    var obj_marker_path = document.createElementNS("http://www.w3.org/2000/svg", "path");
    var path_d = "M0,1 L0,7 L8,4 z";

    obj_marker_path.setAttribute("d", path_d);
    obj_marker_path.setAttribute("style", "fill:" + marker_col + "");

    // obj_svg_marker.append(obj_marker_path);
    obj_svg_marker.appendChild(obj_marker_path);

    return obj_svg_marker;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    一组hub值连线
 * 参数:
 *    @param { Promise<String> } jx_val 参数jx值
 *    @param { Promise<String> } b_update_center 撤销重做时传入更新中心标识
 * 返回:
 *    NA
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2021-01-19
 *       内容 : 所有代码
************************************************************************************************/
function connect_group(jx_val, b_update_center) {
    if ("string" !== typeof jx_val) {
        return;
    }

    jx_val = jx_val.trim();

    var arr_jx = obj_same_hub_queue[jx_val];

    if (!mc_util_is_array(arr_jx)) {
        return;
    }

    var ui_jx_len = arr_jx.length;

    if (0 === ui_jx_len) {
        return;
    }

    // just one mod
    if (1 === ui_jx_len) {
        var obj_item = arr_jx[0][0];
        var mod_list = get_mod_chi_obj(obj_item.children[0].children, "mod_list_idx");

        obj_item.classList.remove("hub_children");
        mc_update_line_id(jx_val, obj_item, b_update_center);

        if (mod_list) {
            // 队列显示下标
            mod_list.innerHTML = 1;

            // save line data
            obj_item.LINE_INDEX_SHOW = 1;
            obj_item.LINE_KEY = jx_val;
        }

        return;
    }


    // multiple mod
    for (var line_idx = 0; line_idx < ui_jx_len; line_idx++) {
        if (arr_jx[line_idx]) {
            var item = arr_jx[line_idx][0];
            // add  idx
            var mod_list_i = get_mod_chi_obj(item.children[0].children, "mod_list_idx");

            // 存储id更新中心标识
            mc_update_line_id(jx_val, item, b_update_center);

            if (mod_list_i) {
                var ui_idx = Number(line_idx + 1);

                // 队列显示下标
                mod_list_i.innerText = ui_idx;

                // save line data
                item.LINE_INDEX_SHOW = ui_idx;
                item.LINE_KEY = jx_val;
            }

            // add class
            if (0 !== line_idx) {
                // 同一个hub值的模组连线之后；不是第一个的需要隐藏hub_jx值；
                item.classList.add("hub_children");
            } else {
                item.classList.remove("hub_children");
            }

            // line
            if (line_idx !== ui_jx_len - 1) {
                // var strat_div = get_div_data(item);
                // var end_div = get_div_data(arr_jx[line_idx + 1][0]);

                connect_line_mod(get_div_data(item), get_div_data(arr_jx[line_idx + 1][0]));
            }
        }
    }
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    循环两两模组连线
 * 参数:
 *    @param { Promise<Object> } obj_start 开始块连接点数据对象
 *    @param { Promise<Object> } obj_end 结束块连接点数据对象
 * 返回:
 *    @returns { Promise<Boolean> } false === 参数错误
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2021-01-19
 *       内容 : 所有代码
************************************************************************************************/
function connect_line_mod(obj_start, obj_end) {
    if (!mc_util_is_object(obj_start) || !mc_util_is_object(obj_end)) {
        return false;
    }

    // var line_id = obj_start.id + "_" + obj_end.id;
    var line_id = mc_constrct_line_id(obj_start, obj_end);
    var obj_edit_line = document.getElementById(line_id) || document.getElementById(obj_end.id + "_" + obj_start.id);

    if (obj_edit_line) {
        obj_edit_line.setAttribute("x1", obj_start.left);
        obj_edit_line.setAttribute("y1", obj_start.top);
        obj_edit_line.setAttribute("x2", obj_end.left);
        obj_edit_line.setAttribute("y2", obj_end.top);

        return true;
    }

    // judge show or hide mod line  1 === show || 0 === hide
    var str_mod_line_wrap_div_class = "";

    if (1 !== g_ary_info_disp[g_ary_info_disp.length - 1]) {
        str_mod_line_wrap_div_class += " mod_line_hide";
    }

    var obj_line_res = mc_construct_line(line_id, obj_start.left, obj_start.top, obj_end.left, obj_end.top, str_mod_line_wrap_div_class);

    if (obj_line_res) {
        obj_svg_line_wrap.appendChild(obj_line_res.svg_marker);
        obj_svg_line_wrap.appendChild(obj_line_res.svg_line);
    }

    return true;
}


// **************************************** 优化移动回调 **************************************** //
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    移动线条操作
 * 参数:
 *    @param { Promise<String> } obj_que 连线队列
 *    @param { Promise<String> } arr_sel 框选的对象
 * 返回:
 *    NA
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-11-27
 *       内容 : 所有代码
 ************************************************************************************************/
function move_block_opration(obj_que, arr_sel) {
    if (!mc_util_is_object(obj_que) || !mc_util_is_array(arr_sel)) {
        return;
    }

    var ui_block_len = arr_sel.length;

    for (var ui_block_i = 0; ui_block_i < ui_block_len; ui_block_i++) {
        var $obj_block = arr_sel[ui_block_i];
        var obj_block = $obj_block[0];

        if (!obj_block) {
            continue;
        }

        // var cur_mod_hub = get_mod_chi_obj(obj_block.children[1].children, "mod_hub_div");

        // if (!cur_mod_hub) {
        //     continue;
        // }

        // var hun_val = cur_mod_hub.innerText;

        var hun_val = $obj_block.children(".mod_hub_box").children(".mod_hub_div").text();

        if (hun_val === str_mod_init_val) {
            continue;
        }

        hun_val = mc_get_line_key(b_add_screen, $obj_block, hun_val);

        // 队列内的一组模块
        var arr_gp_block = obj_que[hun_val];

        if (!arr_gp_block) {
            continue;
        }

        var ui_gp_block_len = arr_gp_block.length;

        if (0 === ui_gp_block_len || 1 === ui_gp_block_len) {
            continue;
        }

        var mod_list_i = get_mod_chi_obj(obj_block.children[0].children, "mod_list_idx");

        if (!mod_list_i) {
            continue;
        }

        var ui_list_i = Number(mod_list_i.innerText);

        if (ui_list_i) {
            var ui_idx_que = ui_list_i - 1;
            var $obj_que_block = arr_gp_block[ui_idx_que];

            if (!$obj_que_block) {
                continue;
            }

            // 当前块中心点数据
            var obj_cur_data = get_div_data($obj_que_block[0]);

            if (ui_idx_que === ui_gp_block_len - 1) {
                move_line_opration(get_div_data(arr_gp_block[ui_idx_que - 1][0]), obj_cur_data);
            } else if (0 === ui_idx_que) {
                move_line_opration(obj_cur_data, get_div_data(arr_gp_block[ui_idx_que + 1][0]));
            } else {
                move_line_opration(get_div_data(arr_gp_block[ui_idx_que - 1][0]), obj_cur_data);
                move_line_opration(obj_cur_data, get_div_data(arr_gp_block[ui_idx_que + 1][0]));
            }
        }
    }
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    移动线操作
 * 参数:
 *    @param { Promise<String> } obj_start 线条开始块数据
 *    @param { Promise<String> } obj_end 线条结束块数据
 * 返回:
 *    NA
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-11-27
 *       内容 : 所有代码
 ************************************************************************************************/
function move_line_opration(obj_start, obj_end) {
    if (!mc_util_is_object(obj_start) || !mc_util_is_object(obj_end)) {
        return;
    }

    // var line_id = obj_start.id + "_" + obj_end.id;
    var line_id = mc_constrct_line_id(obj_start, obj_end);
    var obj_line = document.getElementById(line_id);

    if (obj_line) {
        obj_line.setAttribute("x1", obj_start.left);
        obj_line.setAttribute("y1", obj_start.top);

        obj_line.setAttribute("x2", obj_end.left);
        obj_line.setAttribute("y2", obj_end.top);
    }
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    移动更新线条(实时)
 * 参数:
 *    @param { Promise<String> } obj_que 连线队列
 *    @param { Promise<String> } arr_sel 框选的对象
 * 返回:
 *    NA
 * 例子:
 *    NA
 * 备注:
 *    使用保存参数; LINE_INDEX_SHOW === 该模块在队列的位置(显示的位置从1开始); LINE_KEY === 该模块在队列的key值
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2021-01-23
 *       内容 : 所有代码
************************************************************************************************/
function mc_update_line_when_move(obj_que, arr_sel) {
    if (!mc_util_is_object(obj_que) || !mc_util_is_array(arr_sel)) {
        return;
    }

    var ui_block_len = arr_sel.length;

    for (var ui_block_i = 0; ui_block_i < ui_block_len; ui_block_i++) {
        var $obj_block = arr_sel[ui_block_i];

        if (0 === $obj_block.length) {
            continue;
        }

        var obj_i = $obj_block[0];

        // this key is show index value
        var ui_idx = obj_i.LINE_INDEX_SHOW;

        if (!ui_idx) {
            continue;
        }

        var arr_gp_block = obj_que[obj_i.LINE_KEY];

        if (!arr_gp_block) {
            continue;
        }

        var ui_gp_block_len = arr_gp_block.length;

        if (0 === ui_gp_block_len || 1 === ui_gp_block_len) {
            continue;
        }


        // idx in queue need -1
        var ui_idx_que = Number(ui_idx) - 1;
        var $obj_que_block = arr_gp_block[ui_idx_que];

        if (!$obj_que_block) {
            continue;
        }

        var obj_cur_data = get_div_data($obj_que_block[0]);

        if (ui_idx_que === ui_gp_block_len - 1) {
            move_line_opration(get_div_data(arr_gp_block[ui_idx_que - 1][0]), obj_cur_data);
        } else if (0 === ui_idx_que) {
            move_line_opration(obj_cur_data, get_div_data(arr_gp_block[ui_idx_que + 1][0]));
        } else {
            move_line_opration(get_div_data(arr_gp_block[ui_idx_que - 1][0]), obj_cur_data);
            move_line_opration(obj_cur_data, get_div_data(arr_gp_block[ui_idx_que + 1][0]));
        }
    }
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    移动时显示或隐藏线条(单条)
 * 参数:
 *    @param { Promise<Object> } obj_que 连线队列
 *    @param { Promise<Object> } $obj_i 单个模组 jq 对象
 *    @param { Promise<Boolean> } b_show 显示或隐藏
 * 返回:
 *    @returns { Promise<Boolean> } false === 参数或其他错误错误
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2021-02-03
 *       内容 : 所有代码
************************************************************************************************/
function mc_display_line_when_move(obj_que, $obj_i, b_show) {
    if ("object" !== typeof obj_que || "object" !== typeof $obj_i || "boolean" !== typeof b_show) {
        return false;
    }

    var obj_i = null;
    var arr_gp_block = "";

    if (1 !== $obj_i.length || (obj_i = $obj_i[0]) || !obj_i.LINE_INDEX_SHOW || (arr_gp_block = obj_que[obj_i.LINE_KEY])) {
        return false;
    }

    var ui_gp_block_len = arr_gp_block.length;

    if (0 === ui_gp_block_len || 1 === ui_gp_block_len) {
        return false;
    }

    var ui_idx_que = Number(obj_i.LINE_INDEX_SHOW) - 1;
    var $obj_que_block = arr_gp_block[ui_idx_que];

    if (!$obj_que_block) {
        return false;
    }

    if (ui_idx_que === ui_gp_block_len - 1) {
        show_or_not(document.getElementById(mc_constrct_line_id(arr_gp_block[ui_idx_que - 1][0], $obj_que_block[0])));
    } else if (0 === ui_idx_que) {
        show_or_not(document.getElementById(mc_constrct_line_id($obj_que_block[0], arr_gp_block[ui_idx_que + 1][0])));
    } else {
        show_or_not(document.getElementById(mc_constrct_line_id(arr_gp_block[ui_idx_que - 1][0], $obj_que_block[0])));
        show_or_not(document.getElementById(mc_constrct_line_id($obj_que_block[0], arr_gp_block[ui_idx_que + 1][0])));
    }


    // 显示或隐藏
    function show_or_not(obj) {
        if (obj) {
            if (b_show) {
                obj.style.display = "block";
            } else {
                obj.style.display = "none";
            }
        }
    }

    return true;
}


// **************************************** 创建线条, 更新连线 **************************************** //


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取背景颜色css规则
 * 参数:
 *    @param { Promise<String> } val 块内值 不包含 P || J
 * 返回:
 *    @returns { Promise<String> } 返回相应的颜色css规则
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-9-4
 *       内容 : 所有代码
 ************************************************************************************************/
function get_bgc_css(val) {
    var int_val = Number(val);

    var pre = "background-color:";
    var suf = " !important;";

    // randen color
    return pre + g_arr_color[int_val * 2 - 1] + suf;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    创建一组颜色值
 * 参数:
 *    NA
 * 返回:
 *    @returns { Promise<String> } 一组颜色值
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-9-4
 *       内容 : 所有代码
 ************************************************************************************************/
function create_grp_color() {
    var arr_color = [];
    var step = 7;

    for (var i = 0; i < step; i++) {
        for (var j = 0; j < step; j++) {
            var rem = 255 / step;
            var color = "rgb(" + Math.floor(255 - rem * j) + "," + Math.floor(255 - rem * i) + "," + Math.floor(255 - rem * i) + ")";

            arr_color.push(color);
        }
    }

    return arr_color;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取合并模组数据; 判断模组是否可以合并 && 对模组排序 && 按模式合并模组
 * ��数:
 *    @param { Promise<Number> } mode 合并模式 1 === 普通合并 || 2 === 多路时钟合并
 *    @param { Promise<Array> } arr_mod 需要合并的模组框选数据 (框选对象对象集合)
 *    @param { Promise<Array> } arr_mod_data 模组页面保存的模组数据 数组
 *    @param { Promise<string> } str_scan_merge 普通合并模式下 0 ->STR合并  1->行扫合并
 * 返回:
 *    @returns { Promise<Boolean> } false === 合并条件不成立 || 返回可以合并的并且排序的模组数据
 * 例子:
 *    NA
 * 备注:
 *    合并条件:
 *    1.普通合并:
 *      a.芯片名称必需一样（包括显示芯片，行管芯片）
 *      b.行扫数量要一样
 *    2.多路时钟合并:
 *      a.芯片名称必需一样（包括显示芯片，行管芯片）
 *      b.STR数量要一样
 *      c.行扫数量要一样
 *      d.行长（单扫的灯珠数）要一样 === 数据最内层数据
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-9-24
 *       内容 : 所有代码
 ************************************************************************************************/
function get_mod_merge_data(mode, arr_mod, arr_mod_data, str_scan_merge) {
    if ("number" !== typeof mode || "[object Array]" !== Object.prototype.toString.call(arr_mod) || "[object Array]" !== Object.prototype.toString.call(arr_mod_data)) {
        return false;
    }


    var b_mode = false;

    switch (mode) {
        case 1:
            b_mode = true;
            break;
        case 2:
            b_mode = true;
            break;
        case 3:
            b_mode = true;
            break;
        default:
            break;
    }

    if (!b_mode) {
        return false;
    }

    var ui_mod_len = arr_mod.length;
    // set up key - value obj; key === mod_name; value === mod merge condition
    var obj_mod = {};

    // base value
    var obj_base = false;
    // find arr min x and y
    var ui_min_x = null;
    var ui_min_y = null;

    // init get mod list data;like as pos
    function init_get_mod_data() {
        // sort mode
        var arr_save_mod_data = [];

        for (var mod_i = 0; mod_i < ui_mod_len; mod_i++) {
            var $obj_item = arr_mod[mod_i];

            if (1 !== $obj_item.length) {
                continue;
            }

            var obj_item = $obj_item[0];
            var pos = get_mod_chi_obj(obj_item.children[0].children, "mod_pot");

            if (!pos) {
                return false;
            }

            var cui_reg_int = /[\d.]+/g;
            var ui_x = Number(pos.innerHTML.match(cui_reg_int)[0]);
            var ui_y = Number(pos.innerHTML.match(cui_reg_int)[1]);

            var str_mod_name = obj_item.getAttribute("mod_id");

            if (str_mod_name) {
                // init min x y value
                if (null === ui_min_x) {
                    ui_min_x = ui_x;
                }

                if (null === ui_min_y) {
                    ui_min_y = ui_y;
                }

                // change min x y
                if (ui_x < ui_min_x) {
                    ui_min_x = ui_x;
                }

                if (ui_y < ui_min_y) {
                    ui_min_y = ui_y;
                }

                // get mod data
                if (!obj_mod[str_mod_name]) {
                    var cur_mod_data = get_cur_mod_from_mod_list(str_mod_name);

                    if (cur_mod_data) {
                        obj_mod[str_mod_name] = cur_mod_data;
                    } else {
                        return false;
                    }
                }

                if (!obj_base) {
                    // init compare the base data
                    obj_base = obj_mod[str_mod_name];
                    obj_base.MOD_X = ui_x;
                    obj_base.MOD_Y = ui_y;
                    obj_base.idx = mod_i;
                    arr_save_mod_data.push(obj_base);
                    continue;
                }

                // copy mod data
                var obj_cur_name_mod = obj_mod[str_mod_name].COPY();

                if (!can_merge_mod(obj_base, obj_cur_name_mod)) {
                    return false;
                }

                // add mod
                obj_cur_name_mod.MOD_X = ui_x;
                obj_cur_name_mod.MOD_Y = ui_y;
                obj_cur_name_mod.idx = mod_i;
                arr_save_mod_data.push(obj_cur_name_mod);
            }
        }

        return arr_save_mod_data;
    }

    // judge two mod can merge;
    function can_merge_mod(obj_mod1, obj_mod2) {
        // SCANCHIP_NAME
        if (obj_mod1.SCANCHIP_NAME !== obj_mod2.SCANCHIP_NAME) {
            return false;
        }

        // DISPCHIP_NAME
        if (obj_mod1.DISPCHIP_NAME !== obj_mod2.DISPCHIP_NAME) {
            return false;
        }

        if (1 === mode) {
            if (obj_mod1.SCAN_NUM_FIRST !== obj_mod2.SCAN_NUM_FIRST) {
                return false;
            }
        }

        if (2 === mode || 3 === mode) {
            if (obj_mod1.STR_NUM !== obj_mod2.STR_NUM) {
                return false;
            }

            if (!compare_scan_pix_num(obj_mod1, obj_mod2)) {
                return false;
            }
        }

        return true;
    }

    /**
* @description get the modlue date from page mod list
* @param { Promise<String> } name mod name
* @returns { Promise<Object> } obj return mod data || false === not find
*/
    function get_cur_mod_from_mod_list(name) {
        if ("string" !== typeof name) {
            return false;
        }

        var ui_len = arr_mod_data.length;

        for (var idx = 0; idx < ui_len; idx++) {
            var item = arr_mod_data[idx];

            if (item) {
                if (item.name === name) {
                    var obj_sdk_mod_copy = new mc_sdk_module();

                    item.data.mc_util_mod_copy_msg(obj_sdk_mod_copy);

                    var obj_res = get_mod_merge_mode_condition_data(obj_sdk_mod_copy);

                    if (obj_res) {
                        return obj_res;
                    }
                }
            }
        }

        return false;
    }

    /**
* @description get mod merge mode condition date;
* @param { Promise<Number> } obj mod xml === mc_sdk_module
* @returns { Promise<Object> } obj return merge mod format data || false === params error
*/
    function get_mod_merge_mode_condition_data(obj) {
        if ("[object Object]" !== Object.prototype.toString.call(obj)) {
            return false;
        }

        var obj_mod_data = new format_merge_mod_data();
        var obj_sdk_mod = obj;

        obj_mod_data.SCANCHIP_NAME = obj_sdk_mod.mc_util_mod_get_scan_chip();
        obj_mod_data.DISPCHIP_NAME = obj_sdk_mod.mc_util_mod_get_disp_chip();

        obj_mod_data.STR_NUM = obj_sdk_mod.mc_util_mod_get_str_cnt();

        // get STR_0 scan cnt
        obj_mod_data.SCAN_NUM_FIRST = obj_sdk_mod.mc_util_mod_get_scan_cnt(0);

        // set obj_sdk_modlue
        obj_mod_data.OBJ_SDK_MOD = obj_sdk_mod;

        return obj_mod_data;
    }


    /**
* @description 比较单扫内的灯珠数
* @param { Promise<Number> } obj_b mod1(base_mod) format data
* @param { Promise<Number> } obj_c mod2(compared_mod) format data
* @returns { Promise<Boolean> } true === equal || false === no equal
*/
    function compare_scan_pix_num(obj_b, obj_c) {
        var ui_str_loop_num = obj_b.STR_NUM;

        var obj_sdk_mod_b = obj_b.OBJ_SDK_MOD;
        var obj_sdk_mod_c = obj_c.OBJ_SDK_MOD;

        if (!obj_sdk_mod_b || !obj_sdk_mod_c) {
            return false;
        }

        // compare scan len
        for (var ui_str_i = 0; ui_str_i < ui_str_loop_num; ui_str_i++) {
            var ui_scan_num_b = obj_sdk_mod_b.mc_util_mod_get_scan_cnt(ui_str_i);
            var ui_scan_num_c = obj_sdk_mod_c.mc_util_mod_get_scan_cnt(ui_str_i);

            if (ui_scan_num_b !== ui_scan_num_c) {
                return false;
            }

            var ui_scan_loop_num = ui_scan_num_b;

            // compare single scan pix num
            for (var ui_scan_i = 0; ui_scan_i < ui_scan_loop_num; ui_scan_i++) {
                var ui_one_scan_pix_num_b = obj_sdk_mod_b.mc_util_mod_get_pix_cnt(ui_str_i, ui_scan_i);
                var ui_one_scan_pix_num_c = obj_sdk_mod_c.mc_util_mod_get_pix_cnt(ui_str_i, ui_scan_i);

                if (ui_one_scan_pix_num_b !== ui_one_scan_pix_num_c) {
                    return false;
                }
            }
        }

        return true;
    }

    // construct merge mod condition data format
    function format_merge_mod_data() {
        if ("[object Object]" !== Object.prototype.toString.call()) {
            // return false;
        }

        // common condition
        this.SCANCHIP_NAME = null;
        this.DISPCHIP_NAME = null;

        // position
        this.MOD_X = null;
        this.MOD_Y = null;

        // mod data
        this.STR_NUM = null;
        // just idx === 0 scan cnt
        this.SCAN_NUM_FIRST = null;

        // save sdk mod construct
        this.OBJ_SDK_MOD = null;

        // defiend offset to base pos
        this.OFFSET_X = null;
        this.OFFSET_Y = null;

        // saved input data
        // this.RAW_DATA = null;

        // copy this obj
        this.COPY = function name() {
            var obj_copy = new format_merge_mod_data();
            var arr_key = Object.keys(this);
            var ui_key_len = arr_key.length;

            for (var key_i = 0; key_i < ui_key_len; key_i++) {
                var str_key = arr_key[key_i];

                if ("OBJ_SDK_MOD" !== str_key) {
                    obj_copy[str_key] = this[str_key];
                }
            }

            var obj_sdk_mod_copy = new mc_sdk_module();

            // copy mc_sdk_modlue
            this.OBJ_SDK_MOD.mc_util_mod_copy_msg(obj_sdk_mod_copy);

            // Assignment
            obj_copy.OBJ_SDK_MOD = obj_sdk_mod_copy;

            return obj_copy;
        };

        return true;
    }

    /**
* @description quick sort mod list according to offset total position
* @param { Promise<Array> } arr === Unsorted array
* @returns { Promise<Array> } Sorted array && Modify the original array
*/
    function sort_mod_quick(arr) {
        if ("[object Array]" !== Object.prototype.toString.call(arr)) {
            return false;
        }
        var ui_len = arr.length;

        if (2 > ui_len) {
            return arr;
        }
        // defined ruler
        var ui_ruler = 0;
        // defined exchange position idx
        var ui_ex_idx = 1;

        // for start on i === 1
        for (var i = 1; i < ui_len; i++) {
            // item ----------------------------
            var obj_i = arr[i];
            // item offset
            var ui_i_offset_x = obj_i.MOD_X - ui_min_x;
            var ui_i_offset_y = obj_i.MOD_Y - ui_min_y;

            // change offset
            obj_i.OFFSET_X = ui_i_offset_x;
            obj_i.OFFSET_Y = ui_i_offset_y;

            // ruler ----------------------------
            var obj_ruler = arr[ui_ruler];
            // ruler offset
            var ui_ruler_offset_x = arr[ui_ruler].MOD_X - ui_min_x;
            var ui_ruler_offset_y = arr[ui_ruler].MOD_Y - ui_min_y;

            // change ruler offset
            obj_ruler.OFFSET_X = ui_ruler_offset_x;
            obj_ruler.OFFSET_Y = ui_ruler_offset_y;

            var b_change = false;

            // sort acrodding to mode;
            switch (mode) {
                case 2:
                    if (ui_i_offset_x < ui_ruler_offset_x) {
                        b_change = true;
                    }
                    break;
                case 3:
                    if (ui_i_offset_y < ui_ruler_offset_y) {
                        b_change = true;
                    }
                    break;
                default:
                    // default sort compare total offset; this mode === 1
                    var ui_i_total_offset = ui_i_offset_x + ui_i_offset_y;
                    var ui_ruler_total_offset = ui_ruler_offset_x + ui_ruler_offset_y;

                    if (ui_i_total_offset < ui_ruler_total_offset) {
                        b_change = true;
                    }
                    break;
            }

            // change position
            if (b_change) {
                var obj_temp_in = arr[i];

                arr[i] = arr[ui_ex_idx];
                arr[ui_ex_idx] = obj_temp_in;
                ui_ex_idx++;
            }
        }

        // fistr loop end; change ruler idx to exchange pos pre pos
        var obj_temp_out = arr[ui_ex_idx - 1];

        arr[ui_ex_idx - 1] = arr[ui_ruler];
        arr[ui_ruler] = obj_temp_out;

        return sort_mod_quick(arr.slice(0, ui_ex_idx - 1)).concat(
            arr[ui_ex_idx - 1],
            sort_mod_quick(arr.slice(ui_ex_idx, ui_len))
        );
    }

    /**
* @description merge mod when mode === 1
* @param { Promise<Array> } arr_sort_mod === Sorted array
* @param { Promise<string> } str_scan_type === merge scan
* @returns { Promise<Object> } new mod format data || false
*/
    function merge_mod(arr_sort_mod, str_scan_type) {
        if ("[object Array]" !== Object.prototype.toString.call(arr_sort_mod)) {
            return false;
        }
        var ui_len = arr_sort_mod.length;
        var obj_new_mod = arr_sort_mod[0].COPY();
        var ui_new_str_i = 0;

        // reset array
        obj_new_mod.OBJ_SDK_MOD.mc_util_mod_get_str_ary().length = 0;

        // str合并
        if (0 === str_scan_type) {
            for (var com_i = 0; com_i < ui_len; com_i++) {
                var obj_i = arr_sort_mod[com_i];
                var obj_sdk_mod_i = obj_i.OBJ_SDK_MOD;
                var ui_str_len = obj_i.STR_NUM;

                for (var str_i = 0; str_i < ui_str_len; str_i++) {
                    var ui_scan_len = obj_sdk_mod_i.mc_util_mod_get_scan_cnt(str_i);

                    if (0 !== obj_i.OFFSET_X || 0 !== obj_i.OFFSET_Y) {
                        for (var scan_i = 0; scan_i < ui_scan_len; scan_i++) {
                            var ui_pix_len = obj_sdk_mod_i.mc_util_mod_get_pix_cnt(str_i, scan_i);

                            for (var pix_i = 0; pix_i < ui_pix_len; pix_i++) {
                                var obj_old_pix = obj_sdk_mod_i.mc_util_mod_get_pix_info(str_i, scan_i, pix_i);

                                var ui_new_x = obj_old_pix.u32_img_x + obj_i.OFFSET_X;
                                var ui_new_y = obj_old_pix.u32_img_y + obj_i.OFFSET_Y;

                                // 1. change pix information
                                obj_sdk_mod_i.mc_util_mod_set_pix_info(str_i, scan_i, pix_i, ui_new_x, ui_new_y, obj_old_pix.c_color);
                            }
                        }
                    }


                    // 2. change str_name && pin_name
                    if (0 !== com_i) {
                        var str_name_prefix = "STR_";
                        var str_new_str_name = str_name_prefix + ui_new_str_i;

                        obj_sdk_mod_i.mc_util_mod_set_str_name(str_i, str_new_str_name);
                        obj_sdk_mod_i.mc_util_mod_set_str_pin(str_i, str_new_str_name);
                    }


                    // 3. set new mod STR array
                    obj_new_mod.OBJ_SDK_MOD.mc_util_mod_get_str_ary().push(obj_sdk_mod_i.mc_util_mod_get_str_ary()[str_i]);
                    ui_new_str_i++;
                }
            }
        } else {
            // scan合并 线数不统一不变 每条线的每一扫进行合并
            // 线条数
            var ui_str_length = arr_sort_mod[0].COPY().STR_NUM;
            // 扫数数 每个
            var ui_scan_each_length = arr_sort_mod[0].COPY().SCAN_NUM_FIRST;
            // 合并模组的数量
            var ui_mod_cnt = arr_sort_mod.length;

            // 创建临时模组存放线
            var obj_temp_mod = arr_sort_mod[0].COPY().OBJ_SDK_MOD;

            // 定义每一扫应添加的点数
            var ui_pix_cnt = -1;

            // 线
            for (var idx_str = 0; idx_str < ui_str_length; idx_str++) {
                // 请空每条线
                obj_temp_mod.mc_util_mod_reset_str_pix(idx_str);
                // 每个模组的单扫
                for (var idx_scan = 0; idx_scan < ui_scan_each_length; idx_scan++) {
                    ui_pix_cnt = -1;
                    // 模组
                    for (var idx_mod = 0; idx_mod < ui_mod_cnt; idx_mod++) {
                        var obj_each_mod = arr_sort_mod[idx_mod];
                        // 模组所有点数
                        var obj_each_mod_data = obj_each_mod.OBJ_SDK_MOD;
                        // 获取每个模组的单扫点数
                        var ui_scan_pix_len = obj_each_mod_data.mc_util_mod_get_pix_cnt(idx_str, idx_scan);

                        for (var idx_pix = 0; idx_pix < ui_scan_pix_len; idx_pix++) {
                            ui_pix_cnt++;
                            var obj_old_pix_val = obj_each_mod_data.mc_util_mod_get_pix_info(idx_str, idx_scan, idx_pix);

                            var ui_new_scan_x = obj_old_pix_val.u32_img_x + obj_each_mod.OFFSET_X;
                            var ui_new_scan_y = obj_old_pix_val.u32_img_y + obj_each_mod.OFFSET_Y;

                            // 1. change pix information
                            obj_temp_mod.mc_util_mod_set_pix_info(idx_str, idx_scan, ui_pix_cnt, ui_new_scan_x, ui_new_scan_y, obj_old_pix_val.c_color);
                        }
                    }
                }

                obj_new_mod.OBJ_SDK_MOD.mc_util_mod_get_str_ary().push(obj_temp_mod.mc_util_mod_get_str_ary()[idx_str]);
            }
        }


        return obj_new_mod;
    }

    /**
* @description merge mod when mode === 2 || 3
* @param { Promise<Array> } arr_sort_mod === Sorted array
* @returns { Promise<Object> } new mod format data || false
*/
    function merge_mod_multi_clock(arr_sort_mod) {
        if ("[object Array]" !== Object.prototype.toString.call(arr_sort_mod)) {
            return false;
        }

        var obj_new_mod = arr_sort_mod[0].COPY();

        // change pix length
        var ui_new_mod_str = obj_new_mod.STR_NUM;
        var obj_new_mod_sdk = obj_new_mod.OBJ_SDK_MOD;

        for (var str_i = 0; str_i < ui_new_mod_str; str_i++) {
            var ui_scan_len = obj_new_mod_sdk.mc_util_mod_get_scan_cnt(str_i);

            for (var scan_i = 0; scan_i < ui_scan_len; scan_i++) {
                var ui_pix_len = obj_new_mod_sdk.mc_util_mod_get_pix_cnt(str_i, scan_i);

                // reset new mod pix
                obj_new_mod_sdk.mc_util_mod_reset_scan_pix(str_i, scan_i);

                // test view
                // var new_arr = obj_new_mod_sdk.mc_util_mod_get_str_ary();

                // insert sotr mod pix
                for (var pix_i = 0; pix_i < ui_pix_len; pix_i++) {
                    set_new_pix_loop(obj_new_mod_sdk, arr_sort_mod, str_i, scan_i, pix_i);
                }
            }
        }

        return obj_new_mod;
    }

    /**
* @description  when mode === 2 || 3；set new mod pix
* @param { Promise<Array> } obj_new_sdk === new mod mc_sdk_moldue
* @param { Promise<Array> } arr_sort === Sorted array
* @param { Promise<Array> } ui_str === STR index
* @param { Promise<Array> } ui_scan === SCAN index
* @param { Promise<Array> } ui_pix === PIX index
*/
    function set_new_pix_loop(obj_new_sdk, arr_sort, ui_str, ui_scan, ui_pix) {
        var ui_len = arr_sort.length;

        for (var i_mod = 0; i_mod < ui_len; i_mod++) {
            var obj_sort_mod_i = arr_sort[i_mod];
            var obj_sort_mod_sdk_i = obj_sort_mod_i.OBJ_SDK_MOD;

            // test view
            // var arr_i = obj_sort_mod_sdk_i.mc_util_mod_get_str_ary();

            // get pix infor
            var obj_pix_i = obj_sort_mod_sdk_i.mc_util_mod_get_pix_info(ui_str, ui_scan, ui_pix);

            var ui_push_x = obj_pix_i.u32_img_x + obj_sort_mod_i.OFFSET_X;
            var ui_push_y = obj_pix_i.u32_img_y + obj_sort_mod_i.OFFSET_Y;
            var str_push_color = obj_pix_i.c_color;
            var ui_push_pix_i = ui_len * ui_pix + i_mod;

            // set new pix && push
            obj_new_sdk.mc_util_mod_set_pix_info(ui_str, ui_scan, ui_push_pix_i, ui_push_x, ui_push_y, str_push_color);
        }
    }


    // set this function return create new mod data format; obj_new_mod === create new mod; ui_num === merge num
    function set_result_data(obj_new_mod, ui_num) {
        // var str_new_mod_size = obj_new_mod.OBJ_SDK_MOD.mc_util_mod_get_width() + "_" + obj_new_mod.OBJ_SDK_MOD.mc_util_mod_get_height();
        var str_new_mod_name = "MOD_MERGE_" + obj_new_mod.DISPCHIP_NAME + "_" + ui_num;

        // construct return new mod data
        var res_mod_data = {
            "name": str_new_mod_name,
            "data": obj_new_mod.OBJ_SDK_MOD,
            "x": ui_min_x,
            "y": ui_min_y
        };

        return res_mod_data;
    }

    var res_can_merge = init_get_mod_data();

    if (!res_can_merge) {
        return false;
    }

    // sort mod
    var arr_res = sort_mod_quick(res_can_merge);

    // 根据界面顺序进行排序模组
    var arr_res_end = mc_sort_mod(arr_res);

    function mc_sort_mod(arr) {
        var ui_len = arr.length;
        var arr_idx = new Array(ui_len);
        var arr_return = new Array(ui_len);

        // 根据idx进行排序最终合并
        for (var id = 0; id < ui_len; id++) {
            arr_idx[id] = arr[id].idx;
        }

        for (var key = 0; key < ui_len; key++) {
            for (var key_o = 0; key_o < ui_len; key_o++) {
                if (arr_idx[key_o] === key) {
                    arr_return[key] = arr[key_o];
                }
            }
        }

        return arr_return;
    }


    if (1 === mode) {
        return set_result_data(merge_mod(arr_res_end, str_scan_merge), arr_res_end.length);
    }

    if (2 === mode || 3 === mode) {
        return set_result_data(merge_mod_multi_clock(arr_res_end), arr_res_end.length);
    }

    return false;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    该构造函数用于设置获取card输出口图像负荷参数
 * 参数:
 *    NA
 * 返回:
 *    NA
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-09-25
 *       内容 : 所有代码
 ************************************************************************************************/
function format_card_output_load() {
    var m_obj_param_card = {};

    /************************************************************************************************
* 类型:
*    函数
* 功能:
*    设置获取卡输出图像参数对象
* 参数:
*    @param { Promise<String> } name_id json串的属性name_id值
*    @param { Promise<String> } pos 计算机连接的第几张发送卡，大于等于0 || 当为获取hub卡时；值为表达式（SEND_IDX:SEND_PORT:HUB_IDX）
*    @param { Promise<String> } width 带载的图像宽
*    @param { Promise<String> } height 带载的图像高
* 返回:
*    @returns { Promise<String> } 参数1
* 例子:
*    NA
* 备注:
*    NA
* 修改:
*    1. 类型 : 创建
*       作者 : 巫昭雯
*       时间 : 2020-09-25
*       内容 : 所有代码
************************************************************************************************/
    this.set_obj_param = function (name_id, pos, width, height) {
        if ("string" !== typeof name_id || "string" !== typeof pos || "string" !== typeof width || "string" !== typeof height) {
            return false;
        }

        var obj = {
            POS: pos,
            WIDTH: width,
            HEIGHT: height,
            PERCENT: null
        };

        if (m_obj_param_card[name_id]) {
            m_obj_param_card[name_id].push(obj);
        } else {
            m_obj_param_card[name_id] = [obj];
        }

        return true;
    };

    // 获取设置的参数对象
    this.get_param_obj = function () {
        return m_obj_param_card;
    };

    // 清空参数对象
    this.reset = function () {
        m_obj_param_card = {};
    };

    // juged has params
    this.has_param = function () {
        return 0 === Object.keys(m_obj_param_card).length ? false : true;
    };

    // 设置百分比
    this.set_percent = function (key, i, pre) {
        if ("number" !== typeof pre) {
            return false;
        }
        var str_key = m_obj_param_card[key];

        if (str_key && str_key[i]) {
            str_key[i].PERCENT = pre;
            return true;
        }

        return false;
    };
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取发送卡或hub卡输出口图像负荷
 * 参数:
 *    @param { Promise<Number> } type 1 === HUBCARD_OUTPORT_LOAD 获取HUB卡输出口图像负荷  || 其他 === 获取发送卡输出口图像负荷
 *    @param { Promise<String> } card_name HUB卡或发送卡名称，drivers中注册名，可通过获取参数得到;
 *    @param { Promise<Object> } obj_load_param json串传递的param参数对象 调用format_hub_output_load设置；
 *    @param { Promise<Function> } callback 读取卡输出口图像负荷之后的回调;回调参数详情请看备注信息；
 * 返回:
 *    @returns { Promise<Boolean> } true || false; 参数格式是否正确
 * 例子:
 *    NA
 * 备注:
 *    回调有两种情况：1; callback(true, 请求错误码); 2:callback(false, 请求返回的json串)
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-09-25
 *       内容 : 所有代码
 ************************************************************************************************/
function mc_get_card_outport_load(type, card_name, obj_load_param, callback) {
    if ("number" !== typeof type || "string" !== typeof card_name || "[object Object]" !== Object.prototype.toString.call(obj_load_param)) {
        return false;
    }

    if (!(obj_load_param instanceof format_card_output_load)) {
        return false;
    }

    var fun_name = "";

    switch (type) {
        case 1:
            fun_name = "HUBCARD_OUTPORT_LOAD";
            break;
        default:
            fun_name = "SENDCARD_OUTPORT_LOAD";
            break;
    }

    var obj_sdk_param = new mc_sdk_param();
    // var str_param_name = name_id.toUpperCase();

    obj_sdk_param.set_param_clear();
    obj_sdk_param.set_cmd("GET_PARAM");
    obj_sdk_param.set_func(fun_name);

    var obj_load_res = obj_load_param.get_param_obj();
    var arr_name_id = Object.keys(obj_load_res);
    var ui_len = arr_name_id.length;

    for (var idx = 0; idx < ui_len; idx++) {
        var str_param_name = arr_name_id[idx];
        var arr_item = obj_load_res[str_param_name];

        obj_sdk_param.set_param_value(str_param_name, card_name);

        var ui_item_len = arr_item.length;

        for (var i = 0; i < ui_item_len; i++) {
            var item = arr_item[i];

            obj_sdk_param.set_attr_val(str_param_name, "POS", item.POS);
            obj_sdk_param.set_attr_val(str_param_name, "WIDTH", item.WIDTH);
            obj_sdk_param.set_attr_val(str_param_name, "HEIGHT", item.HEIGHT);
        }
    }

    var str = obj_sdk_param.get_json();

    // console.log("[卡加载]",type,JSON.parse(str));

    $.post("/access_shell", str, function (res, status) {
        if ("success" !== status) {
            return;
        }

        obj_sdk_param.set_param_clear();
        obj_sdk_param.set_json(res);
        var str_err = obj_sdk_param.get_param_value("ERROR_CODE");
        // var str_param_err = obj_sdk_param.get_attr_val(str_param_name,"ERROR_CODE");

        if ("function" === typeof callback) {
            var err = true;
            var error_code = "0x00000000";

            if (error_code === str_err || !str_err) {
                err = false;

                callback(err, res);
                return;
            }

            callback(err, res);
        }
    }, "text");

    return true;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    构造模组
 * 参数:
 *    @param {Promise<String>} str_mod_name 模组名称
 *    @param {Promise<Array>} ary_mod_list 模组列表
 *    @param {Promise<Number>} ui_mod_width 模组宽度
 *    @param {Promise<Number>} ui_mod_height 模组高度
 * 返回：
 *    @returns {Promise<String>} 当前使用模组名称或为错误码
 * 备注:
 *    1:参数错误
 *    2:未知错误
 *    3:简易模组条件错误(长或宽等于单扫长度)
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.11.13
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_construct_mod(str_mod_name, ary_mod_list, ui_mod_width, ui_mod_height) {
    // 查询模组所在下标
    var ui_mod_idx = mc_layout_get_data_idx_in_name(ary_mod_list, str_mod_name);

    if ("boolean" === typeof ui_mod_idx) {
        return [false, 1];
    }
    // 获取模板模组
    var obj_tpl_mod = ary_mod_list[ui_mod_idx].data;
    // 构造新模组
    var obj_cst_mod = new mc_sdk_module();

    // 赋值模板模组至构造模组中
    obj_tpl_mod.mc_util_mod_copy_msg(obj_cst_mod);
    // 更新构造模组描点信息为默认描点信息
    var ui_error_code = obj_cst_mod.mc_util_mod_updata_mod_size(ui_mod_width, ui_mod_height);

    // 更新失败则提示错误
    if (0 !== ui_error_code) {
        return [false, (1 + ui_error_code)];
    }
    // 获取当前生成模组下标最大值,如果为-2代表当前模组已存在
    var ui_max_mod_idx = -1;
    // 使用的模组名称 - 存在则使用已存在的模组名称
    var str_use_mod_name = "MC_MOD_";
    // 记录使用模组所在下标
    var ui_use_mod_idx = -1;

    // 查询模组是否存在 及 模组当前使用下标最大值
    for (var idx_name = 0; idx_name < ary_mod_list.length; idx_name++) {
        // 查询模组数据
        var obj_mod_data = ary_mod_list[idx_name];

        // 判断是否存在当前模组
        if (obj_mod_data.data.mc_util_mod_check_equal(obj_cst_mod.mc_util_mod_get_xml())) {
            ui_max_mod_idx = -2;
            str_use_mod_name = obj_mod_data.name;
            ui_use_mod_idx = idx_name;
            break;
        }
        // 获取所有下标中最大值
        ui_mod_idx = Number(obj_mod_data.name.match(/\d+/g)[0]);
        if (ui_mod_idx > ui_max_mod_idx) {
            ui_max_mod_idx = ui_mod_idx;
        }
    }

    // 非-2则代表构造新模组
    if (-2 !== ui_max_mod_idx) {
        str_use_mod_name += (ui_max_mod_idx + 1);
        ary_mod_list.push({
            name: str_use_mod_name,
            data: obj_cst_mod
        });
    }
    return [true, ui_use_mod_idx];
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    构造箱体
 * 参数:
 *    @param {Promise<String>} str_box_name 箱体名称
 *    @param {Promise<Array>} ary_box_list 箱体列表
 *    @param {Promise<Array>} ary_mod_list 模组列表
 *    @param {Promise<Number>} ui_box_width 箱体宽度
 *    @param {Promise<Number>} ui_box_height 箱体高度
 * 返回：
 *    @returns {Promise<String>} 当前使用箱体名称或为错误码
 * 备注:
 *    1:参数错误
 *    2:未知错误
 *    3:简易模组条件错误(长或宽等于单扫长度)
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.11.14
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_construct_box(str_box_name, ary_box_list, ary_mod_list, ui_box_width, ui_box_height) {
    // 查询模组所在下标
    var ui_mod_idx = mc_layout_get_data_idx_in_name(ary_box_list, str_box_name);

    if ("boolean" === typeof ui_mod_idx) {
        return [false, 1];
    }
    var obj_tpl_data = ary_box_list[ui_mod_idx];
    var obj_cst_box = new mc_ui_box();

    // 根据参考箱体下第一个模组创建新的模组
    var str_first_mod_name = obj_tpl_data.data.mc_util_get_box_first_mod_name();

    // 构造箱体下第一个引脚下第一个模组
    var ary_mc_error = mc_layout_construct_mod(str_first_mod_name, ary_mod_list, ui_box_width, ui_box_height);

    if (!ary_mc_error[0]) {
        return ary_mc_error;
    }

    var ary_gamma_val = JSON.parse(JSON.stringify(obj_tpl_data.data.mc_util_get_gamma_val()));

    // 存入模板箱体参数
    obj_cst_box.mc_util_set_gamma_val(ary_gamma_val);
    obj_cst_box.mc_util_get_param().set_json(obj_tpl_data.data.mc_util_get_param().get_json());
    obj_cst_box.mc_util_get_resul().set_json(obj_tpl_data.data.mc_util_get_resul().get_json());
    obj_cst_box.mc_util_get_disp_reg().set_json(obj_tpl_data.data.mc_util_get_disp_reg().get_json());
    obj_cst_box.mc_util_get_disp_reg_list().set_json(obj_tpl_data.data.mc_util_get_disp_reg_list().get_json());
    obj_cst_box.mc_util_get_scan_reg().set_json(obj_tpl_data.data.mc_util_get_scan_reg().get_json());
    obj_cst_box.mc_util_get_scan_reg_list().set_json(obj_tpl_data.data.mc_util_get_scan_reg_list().get_json());
    obj_cst_box.mc_util_set_ui_box_msg({
        ctrlchip_name: obj_tpl_data.data.mc_util_get_ui_box_msg().ctrlchip_name,
        hub_name: obj_tpl_data.data.mc_util_get_ui_box_msg().hub_name,
        ctrlchip_hub_msg: obj_tpl_data.data.mc_util_get_ui_box_msg().ctrlchip_hub_msg,
        edit_val: obj_tpl_data.data.mc_util_get_ui_box_msg().edit_val,
        data: [{
            jx_num: 1,
            children: [{
                module_name: ary_mod_list[ary_mc_error[1].name],
                mirror: "0",
                offset_x: "0",
                offset_y: "0",
                rotation: "0,0,0",
                scale: "0.0,0.0,1.0,1.0",
                cut: "0,0,0,0"
            }]
        }]
    });

    // 记录构造模组名称
    var str_use_box_name = "MC_BOX_";
    // 记录当前箱体数据
    var ui_max_box_idx = -1;
    // 记录当前使用箱体下标(默认为最后一个也就是-1,存在即为存在模箱体下标)
    var ui_use_box_idx = -1;
    var str_box_md5 = mc_crypto_set_box_md5_to_key({
        data: obj_cst_box,
        name: "TEST"
    });

    for (var idx_box_list = 0; idx_box_list < ary_box_list.length; idx_box_list++) {
        var obj_box_data_loc = ary_box_list[idx_box_list];
        var str_box_md5_loc = mc_crypto_set_box_md5_to_key(obj_box_data_loc);

        if (idx_box_list !== ui_max_box_idx && str_box_md5_loc === str_box_md5) {
            ui_max_box_idx = -2;
            ui_use_box_idx = idx_box_list;
            break;
        }
        var ui_box_idx = Number(obj_box_data_loc.name.match(/\d+/g));

        if (ui_box_idx > ui_max_box_idx) {
            ui_max_box_idx = ui_box_idx;
        }
    }
    if (-2 !== ui_max_box_idx) {
        str_use_box_name += (ui_max_box_idx + 1);
        ary_box_list.push({
            name: str_use_box_name,
            data: obj_cst_box
        });
    }

    return [true, ui_use_box_idx];
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    控制页面所有盒子的对应
 * 参数:
 *    NA
 * 返回：
 *    NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.11.19
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_info_disp() {
    var ary_type = [
        // 名称
        "mod_show_name",
        // 芯片名称
        "chip_name",
        // 位置
        "mod_pot",
        // 尺寸
        "mod_size",
        // 端口 或 引脚
        "mod_hub_div",
        // 接收卡 或 模组位置
        "mod_list_idx",
        // 卡位置
        "card_idx",
        // 连线
        "mod_hub_Line "
    ];


    for (var idx = 0; idx < g_ary_info_disp.length; idx++) {
        var ui_is_block = g_ary_info_disp[idx];
        var str_display_val = "none";

        if (ui_is_block) {
            str_display_val = "block";
        }

        if ("mod_hub_Line" === ary_type[idx].trim()) {
            if (1 === ui_is_block) {
                $("." + ary_type[idx]).removeClass("mod_line_hide");
            } else {
                $("." + ary_type[idx]).addClass("mod_line_hide");
            }
        } else {
            $("." + ary_type[idx]).css("display", str_display_val);
        }
    }
}


// **************************************** 简易模式 **************************************** //
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取当前表格缩放尺寸
 * 参数:
 *    NA
 * 返回:
 *    @returns { Promise<Number> } 画布属性值为 grid_w 的值 || 参数错误
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-11-27
 *       内容 : 所有代码
 ************************************************************************************************/
function get_cur_zomm() {
    // var elem = document.getElementById("mc_box_canvasbg");
    var o_parent = document.getElementById("mod_box_next");
    // var str_create_grid = o_parent.getAttribute("create_grid");
    // 当前格子宽度
    var ui_current_size = parseInt(o_parent.getAttribute("grid_w"), 10);

    if (ui_current_size) {
        return ui_current_size;
    }

    return false;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    根据固定宽高生成模组背景灯珠数组
 * 参数:
 *    @param { Promise<String> } width 模组的宽
 *    @param { Promise<String> } height 模组的高
 * 返回:
 *    @returns { Promise<Array> } 生成长度为宽X高的灯珠数据并显示为实体点 || false === 参数格式错误
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-11-27
 *       内容 : 所有代码
 ************************************************************************************************/
function create_bgm_url(width, height) {
    if ("number" !== typeof width || "number" !== typeof height) {
        return false;
    }

    // var ui_len = width * height;
    var arr_pix = [];

    for (var ui_w = 0; ui_w < width; ui_w++) {
        for (var ui_h = 0; ui_h < height; ui_h++) {
            arr_pix.push([ui_w, ui_h]);
        }
    }

    return arr_pix;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    设置简易模式修改模组大小 简易模式 === true 时操作;
 * 参数:
 *    @param { Promise<Boolean> } b_mode 只有 === true 时执行部分操作；即模块的简易模式属性值 b_easy_mode === false 才执行修改大小操作；
 * 返回:
 *    NA
 * 例子:
 *    NA
 * 备注:
 *    该模式下：
 *    1. 即不管它原先是什么尺寸，每个模块显示使用相同的大小进行显示，此时所有模块横平竖直对齐;
 *    2. 模块移动时的步进值为设置的相同大小；
 *    3. 模块移动时步进显示的位置值为原始模组的大小
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-11-27
 *       内容 : 所有代码
 ************************************************************************************************/
function set_easy_mode(b_mode) {
    var o_parent = document.getElementById("mod_box_next");
    var str_create_grid = o_parent.getAttribute("create_grid");
    var ui_zoom = get_cur_zomm();
    var str_no_select_url = false;
    var str_select_url = false;
    // 设置的div实际宽高; 宽高相同
    var ui_div_wh = ui_easy_mode_size * ui_zoom;
    // var obj_style_str = new mc_format_style();

    if ("true" === str_create_grid) {
        // 箱体
        // get bgm url
        var str_img_url = set_mod_bgimg(ui_div_wh, ui_div_wh, create_bgm_url(ui_easy_mode_size, ui_easy_mode_size));

        str_no_select_url = str_img_url[0];
        str_select_url = str_img_url[1];
    }

    var arr_mod = $("#mc_hlever_layout_canvas .mc_mod");
    var ui_len = arr_mod.length;
    // var obj_max = get_max_min_box_size();

    for (var ui_i_mod = 0; ui_i_mod < ui_len; ui_i_mod++) {
        var obj_ele = arr_mod[ui_i_mod];

        if (true === b_mode && "true" === obj_ele.getAttribute("b_easy_mode")) {
            continue;
        }

        obj_ele.setAttribute("b_easy_mode", true);

        // 1. change width
        obj_ele.style.width = ui_div_wh + "px";
        obj_ele.style.height = ui_div_wh + "px";

        // 2.change bgm img
        if ("true" === str_create_grid) {
            if (-1 !== obj_ele.className.indexOf("selected")) {
                obj_ele.style.backgroundImage = "url(" + str_select_url + ")";
            } else {
                obj_ele.style.backgroundImage = "url(" + str_no_select_url + ")";
            }
        }

        // change virtual position ui_vir
        var ui_vir_pos = $(obj_ele).children(".mod_msg_box").children(".mod_pot").text();
        var ui_vir_pos_w = ui_vir_pos.split(",")[0];
        var ui_vir_pos_h = ui_vir_pos.split(",")[1];

        var ui_real_w = obj_ele.getAttribute("mod_wg");
        var ui_real_h = obj_ele.getAttribute("mod_hg");

        // 计算虚拟格子数
        var ui_vit_grid_x = mc_util_round(ui_vir_pos_w / ui_real_w);
        var ui_vit_grid_y = mc_util_round(ui_vir_pos_h / ui_real_h);

        // 3. change grid position -> change mod left and top val
        obj_ele.style.left = ui_vit_grid_x * ui_div_wh + "px";
        obj_ele.style.top = ui_vit_grid_y * ui_div_wh + "px";

        // 变换参数; 存在则保存
        var str_transform = obj_ele.getAttribute("transform_msg");

        if (str_transform) {
            var arr_res = mc_analysis_transform_msg(obj_ele, "all");
            var ary_transform = [arr_res[2][0], arr_res[2][1], arr_res[1], arr_res[3]];
            // 缩放X, 缩放Y, 旋转角度, 镜像类型
            var arr_key = ["MC_LANG_X_DIRECTION", "MC_LANG_Y_DIRECTION", "MC_LANG_ROTATION_ANGLE", "MC_LANG_MIRROR_IMAGE"];
            var obj_trans_data = {};

            for (var ui_i_key = 0; ui_i_key < arr_key.length; ui_i_key++) {
                var item = arr_key[ui_i_key];

                obj_trans_data[item] = {};
                obj_trans_data[item].val = ary_transform[ui_i_key];
            }

            save_transform_data([$(obj_ele)], obj_trans_data);

            // 删除子集的转换
            var arr_chi_msg = $(obj_ele).children(".mod_msg_box").children();
            var arr_chi_hub = $(obj_ele).children(".mod_hub_box").children();

            arr_chi_msg.each(function (idx, el) {
                el.style.transform = "";
            });

            arr_chi_hub.each(function (idx, el) {
                el.style.transform = "";
            });
        } else {
            obj_ele.setAttribute("str_trans", "");
        }

        // delete transform style && transform_msg attribute
        obj_ele.style.transform = "";
        obj_ele.setAttribute("transform_msg", "");
    }


    // change canvas
    update_canvas_w(null, ui_canvasbg_size_w);
    update_canvas_h(null, ui_canvasbg_size_h);
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    简易模式 === false 时操作; 返回原始模式
 * 参数:
 *    NA
 * 返回:
 *    NA
 * 例子:
 *    NA
 * 备注:
 *    流程: 修改宽高,大小,背景图,显示转换信息;
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-11-27
 *       内容 : 所有代码
 ************************************************************************************************/
function back_to_narmal_mode() {
    var o_parent = document.getElementById("mod_box_next");
    var obj_style_str = new mc_format_style();
    // 当前格子宽度
    var ui_cur_zoom = get_cur_zomm();
    var m_arr_mod = $(o_parent).children(".mc_mod");
    var str_mod_attr_easy_mode = "b_easy_mode";

    // 修改模块-大小，位置
    if ("true" === o_parent.getAttribute("create_grid")) {
        change_module_box(m_arr_mod, ui_cur_zoom);
    } else {
        change_module_screen(m_arr_mod, ui_cur_zoom);
    }

    // change canvas
    update_canvas_w(null, ui_canvasbg_size_w);
    update_canvas_h(null, ui_canvasbg_size_h);


    // 设置转换
    function set_transform(obj_ele) {
        var str_trans = obj_ele.getAttribute("str_trans");

        if (str_trans) {
            mc_rotate_scale_apply([$(obj_ele)], JSON.parse(str_trans), false);
            obj_ele.setAttribute("str_trans", "");
        }
    }


    /************************************************************************************************
* 类型:
*    内部函数
* 功能:
*    修改模块显示 - 大屏
* 参数:
*    @param { Promise<String> } arr_box 所有模块 - 箱体
*    @param { Promise<String> } ui_zoom 格子大小
* 返回:
*    NA
* 例子:
*    NA
* 备注:
*    NA
* 修改:
*    1. 类型 : 创建
*       作者 : 巫昭雯
*       时间 : 2021-03-19
*       内容 : 所有代码
************************************************************************************************/
    function change_module_screen(arr_box, ui_zoom) {
        var ui_mod_len = arr_box.length;
        var str_pot = "";

        for (var idx_box = 0; idx_box < ui_mod_len; idx_box++) {
            var obj_box = arr_box[idx_box];

            if (obj_box) {
                obj_box.setAttribute(str_mod_attr_easy_mode, false);

                // position
                str_pot = $(obj_box).children(".mod_msg_box").children(".mod_pot").text();

                // set style; W,H,L,T;
                obj_style_str.clear_data();
                obj_style_str.set_val("width", Number(obj_box.getAttribute("mod_wg")) * ui_zoom);
                obj_style_str.set_val("height", Number(obj_box.getAttribute("mod_hg")) * ui_zoom);
                obj_style_str.set_val("left", Number(str_pot.split(",")[0].trim()) * ui_zoom);
                obj_style_str.set_val("top", Number(str_pot.split(",")[1].trim()) * ui_zoom);
                obj_box.style.cssText += obj_style_str.get_style();

                set_transform(obj_box);
            }
        }
    }


    /************************************************************************************************
* 类型:
*    内部函数
* 功能:
*    修改模块显示 - 箱体
* 参数:
*    @param { Promise<String> } arr_mod 所有模块 - 模组
*    @param { Promise<String> } ui_zoom 单个格子大小
* 返回:
*    NA
* 例子:
*    NA
* 备注:
*    NA
* 修改:
*    1. 类型 : 创建
*       作者 : 巫昭雯
*       时间 : 2021-03-19
*       内容 : 所有代码
************************************************************************************************/
    function change_module_box(arr_mod, ui_zoom) {
        var ary_get_img_url = {};
        var ui_mod_len = arr_mod.length;

        for (var idx_mod = 0; idx_mod < ui_mod_len; idx_mod++) {
            var obj_mod = arr_mod[idx_mod];

            if (obj_mod) {
                obj_mod.setAttribute(str_mod_attr_easy_mode, false);

                var str_mod_id = obj_mod.getAttribute("mod_id");

                // 创建背景
                if (0 === idx_mod || !ary_get_img_url[str_mod_id]) {
                    // div 设置的实际宽高
                    var ui_div_width = Number(obj_mod.getAttribute("mod_wg")) * ui_zoom;
                    var ui_div_height = Number(obj_mod.getAttribute("mod_hg")) * ui_zoom;

                    // 获取对应亮点数组
                    // eslint-disable-next-line no-undef
                    var ary_pix = mc_layout_get_mod_dot_location(str_mod_id, ARY_MOD_DATA);
                    var str_img_url = set_mod_bgimg(ui_div_width, ui_div_height, ary_pix);

                    // 保存创建背景; str_img_url[原始背景, 选中的]
                    ary_get_img_url[str_mod_id] = [ui_div_width, ui_div_height, str_img_url[0], str_img_url[1]];
                }

                // 保存的背景数据
                var arr_val = ary_get_img_url[str_mod_id];
                // position
                var str_pot = $(obj_mod).children(".mod_msg_box").children(".mod_pot").text();

                // set style; W,H,L,T;
                obj_style_str.clear_data();
                obj_style_str.set_val("width", arr_val[0]);
                obj_style_str.set_val("height", arr_val[1]);
                obj_style_str.set_val("left", Number(str_pot.split(",")[0].trim()) * ui_zoom);
                obj_style_str.set_val("top", Number(str_pot.split(",")[1].trim()) * ui_zoom);

                if (-1 !== obj_mod.className.indexOf("selected")) {
                    obj_style_str.set_val("backgroundImage", "url(" + arr_val[3] + ")", null);
                } else {
                    obj_style_str.set_val("backgroundImage", "url(" + arr_val[2] + ")", null);
                }

                obj_mod.style.cssText += obj_style_str.get_style();

                set_transform(obj_mod);
            }
        }
    }
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    简易模式下的操作:当坐标值修改时；更新位置
 * 参数:
 *    @param { Promise<Array> } arr_mod 设置固定位置的模组
 *    @param { Promise<Object> } obj_pos 位置值对象
 * 返回:
 *    NA
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-11-27
 *       内容 : 所有代码
 ************************************************************************************************/
function mc_easy_mode_update_pos(arr_mod, obj_pos) {
    if (!obj_item_checkbox_easy_mode.get_dom_val()) {
        return;
    }

    var ui_len = arr_mod.length;

    for (var ui_mod = 0; ui_mod < ui_len; ui_mod++) {
        var $obj_mod = arr_mod[ui_mod];

        if (0 === $obj_mod.length) {
            continue;
        }

        $obj_mod[0].setAttribute("b_easy_mode", false);
        if (obj_pos && mc_util_is_object(obj_pos)) {
            // $obj_mod.children(".mod_msg_box").children(".mod_pot").text(obj_pos.X + "," + obj_pos.Y);
        }
    }

    set_easy_mode(true);
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    简易模式下保存变换数据
 * 参数:
 *    @param { Promise<String> } arr_mod 设置保存的模组对象; jq对象
 *    @param { Promise<String> } trans_data 保存的变换数据 json串转换后的对象
 * 返回:
 *    NA
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-12-08
 *       内容 : 所有代码
 ************************************************************************************************/
function save_transform_data(arr_mod, trans_data) {
    if ("object" !== typeof arr_mod || "object" !== typeof trans_data) {
        return;
    }

    var ui_len = arr_mod.length;
    var str_data = JSON.stringify(trans_data);

    for (var ui_i = 0; ui_i < ui_len; ui_i++) {
        var obj_ele = arr_mod[ui_i];

        if (0 === obj_ele.length) {
            continue;
        }

        obj_ele[0].setAttribute("str_trans", str_data);
    }
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取现存盒子的宽高(最大或最小)
 * 参数:
 *    @param { Promise<Boolean> } b_min 是否为获取最小值
 * 返回:
 *    @returns { Promise<Object> } 最值盒子大小 { W, H }
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2021-01-05
 *       内容 : 所有代码
************************************************************************************************/
function get_max_min_box_size(b_min) {
    var arr_box = $("#mc_hlever_layout_canvas .mc_mod");
    var ui_len = arr_box.length;

    var ui_size_w = null;
    var ui_size_h = null;

    for (var ui_i = 0; ui_i < ui_len; ui_i++) {
        var ele = arr_box[ui_i];

        if (!ele) {
            continue;
        }

        var ui_w = Number(ele.getAttribute("mod_wg"));
        var ui_h = Number(ele.getAttribute("mod_hg"));

        if (null === ui_size_w && null === ui_size_h) {
            ui_size_w = ui_w;
            ui_size_h = ui_h;
        }

        if (true === b_min) {
            if (ui_w < ui_size_w) {
                ui_size_w = ui_w;
            }

            if (ui_h < ui_size_h) {
                ui_size_h = ui_h;
            }
        } else {
            if (ui_w > ui_size_w) {
                ui_size_w = ui_w;
            }

            if (ui_h > ui_size_h) {
                ui_size_h = ui_h;
            }
        }
    }

    return {
        W: ui_size_w,
        H: ui_size_h
    };
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    设置线条svg层画布大小(具体值带单位)
 * 参数:
 *    @param { Promise<String> } obj_size 设置的具体大小对象 { W: 宽, H:高 }
 * 返回:
 *    @returns { Promise<Boolean> } 设置成功 || 错误
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-11-27
 *       内容 : 所有代码
 ************************************************************************************************/
function mc_set_svg_layer_line_size(obj_size) {
    if (!mc_util_is_object(obj_size)) {
        return false;
    }

    var obj_svg_line_layer = document.getElementById("mc_hl_svg_layer_line");

    if (obj_svg_line_layer) {
        if (obj_size.W && "Infinity%" !== obj_size.H) {
            obj_svg_line_layer.setAttribute("width", obj_size.W);
        }

        if (obj_size.H && "Infinity%" !== obj_size.H) {
            obj_svg_line_layer.setAttribute("height", obj_size.H);
        }
    }

    return true;
}


// **************************************** 坐标尺 **************************************** //
/************************************************************************************************
 * 类型:
 *    构造函数
 * 功能:
 *    坐标尺子构造函数
 * 参数:
 *    @param { Promise<String> } str_box_id 整个箱体dom id; id === "mod_box_next"
 *    @param { Promise<String> } str_canvas_id 画布对象id; id === obj_box_id === "mc_box_canvasbg"
 * 返回:
 *    @returns { Promise<Boolean> } true === 构造成功 || false === 参数错误
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-12-08
 *       内容 : 所有代码
 ************************************************************************************************/
function mc_box_coordinate_ruler(str_box_id, str_canvas_id) {
    if ("string" !== typeof str_box_id || "string" !== typeof str_canvas_id) {
        return false;
    }

    var obj_box = document.getElementById(str_box_id);
    var obj_canvas = document.getElementById(str_canvas_id);

    if (!obj_box || !obj_canvas) {
        return false;
    }

    // 定义
    var str_calss_wrap = "mc_coorfinate_grid_wrap";
    var str_id_head = "mc_coordinate_grid_head";
    var str_id_nav = "mc_coordinate_grid_nav";
    var str_id_all = "mc_coorfinate_grid_all";
    var str_class_general = "mc_coordinate_grid";
    // 块类
    var str_class_single_block = "mc_ruler_div";
    // 样式类
    var str_sel_row_col = "mc_coorfinate_grid_select";
    var str_sel_single = "mc_coorfinate_grid_select_single";
    // 标尺块类选择器
    var str_ruler_block_class = "." + str_calss_wrap + " " + "." + str_class_single_block;
    // 单侧大小; 头 === 高 || 侧边 === 宽
    var ui_size_one_side = 30;


    // **************************************** 函数 **************************************** //
    /************************************************************************************************
* 类型:
*    函数
* 功能:
*    坐标尺缩放更新
* 参数:
*    NA
* 返回:
*    NA
* 例子:
*    NA
* 备注:
*    NA
* 修改:
*    1. 类型 : 创建
*       作者 : 巫昭雯
*       时间 : 2020-12-03
*       内容 : 所有代码
************************************************************************************************/
    function update_ruler_scale() {
        var ui_cur_scale = get_box_scale_multiple() / 100;
        var ui_no_scale = 1 / ui_cur_scale;

        // 头
        $("#" + str_id_head).css({
            "transform": "scaleX(" + ui_cur_scale + ")"
        });

        // 侧边
        $("#" + str_id_nav).css({
            "transform": "scaleY(" + ui_cur_scale + ")"
        });

        // 全部
        $("#" + str_id_all).css({});

        // 文字
        $("." + str_calss_wrap + " " + ".head").css({
            "transform": "scaleX(" + ui_no_scale + ")"
        });

        $("." + str_calss_wrap + " " + ".nav").css({
            "transform": "scaleY(" + ui_no_scale + ")"
        });
    }

    /************************************************************************************************
* 类型:
*    函数
* 功能:
*    初始化标尺事件; 鼠标按下;鼠标释放；鼠标移动事件
* 参数:
*    NA
* 返回:
*    NA
* 例子:
*    NA
* 备注:
*    NA
* 修改:
*    1. 类型 : 创建
*       作者 : 巫昭雯
*       时间 : 2020-12-07
*       内容 : 所有代码
************************************************************************************************/
    function init_ruler_event() {
        var obj = document.querySelector("." + str_calss_wrap);

        if (!obj) {
            return;
        }

        // 是否在当前标尺对象按下
        obj.b_down = false;

        obj.onmousedown = function () {
            // console.log("[鼠标按下]",event);
            this.b_down = true;
        };

        obj.onmouseup = function () {
            // console.log("[鼠标按上]", event);
            if (!this.b_down) {
                return;
            }

            this.b_down = false;
        };

        // 鼠标滑动事件
        obj.onmousemove = function (event) {
            // console.log("[鼠标滑动]", event);

            if (!this.b_down) {
                return;
            }

            var obj_targrt = event.target;

            if (-1 !== obj_targrt.className.indexOf(str_class_single_block)) {
                var str_pos = obj_targrt.getAttribute("pos");

                if (obj_mousedown === str_pos) {
                    $(obj_targrt).addClass(str_sel_row_col);
                }
            }
        };
    }

    /************************************************************************************************
* 类型:
*    函数
* 功能:
*    点击全选标尺
* 参数:
*    @param { Promise<String> } b_has_mod
* 返回:
*    NA
* 例子:
*    NA
* 备注:
*    NA
* 修改:
*    1. 类型 : 创建
*       作者 : 巫昭雯
*       时间 : 2020-12-03
*       内容 : 所有代码
************************************************************************************************/
    function click_all_block(b_has_mod) {
        // console.log("[全选]");

        // 框选回调调用
        var b_res = null;
        var str_type = typeof b_has_mod;
        var obj = null;
        // 标尺块
        var $obj_block = $(str_ruler_block_class);

        // remove single selected
        $obj_block.removeClass(str_sel_single);

        if ("boolean" === str_type) {
            obj = document.getElementById(str_id_all);
            b_res = b_has_mod;
        } else {
            obj = this;
            b_res = select_all_operation();
        }

        // remove row or col selected
        var str_class_name = str_sel_row_col;

        if (b_res) {
            $(obj).addClass(str_class_name);
            $obj_block.addClass(str_class_name);
        } else {
            $(obj).removeClass(str_class_name);
            $obj_block.removeClass(str_class_name);
        }
    }

    /************************************************************************************************
* 类型:
*    函数
* 功能:
*    点击标尺; 标尺点击事件; 行选；列选
* 参数:
*    @param { Promise<String> } obj 点击this对象
* 返回:
*    NA
* 例子:
*    NA
* 备注:
*    1. 点击标尺 === 行选 || 列选
*    2. ctrl + 点击 === 多选行列;
* 修改:
*    1. 类型 : 创建
*       作者 : 巫昭雯
*       时间 : 2020-12-03
*       内容 : 所有代码
************************************************************************************************/
    function click_event(obj) {
        if (obj) {
            var e = event || window.event;
            var b_ctrl_key = e.ctrlKey;
            var arr_pre_sel = [];
            var str_class_name = str_sel_row_col;
            // 标尺块
            var $obj_block = $(str_ruler_block_class);


            if (b_ctrl_key) {
                arr_pre_sel = arr_mod_selected;
                $obj_block.removeClass(str_sel_single);
                $(obj).addClass(str_class_name);
            } else {
                $("#" + str_id_all).removeClass(str_class_name);
                $obj_block.removeClass(str_class_name + " " + str_sel_single);
                $(obj).addClass(str_class_name);
            }


            var str_num = obj.children[0].innerText;
            var ui_num = 0;

            if (str_num) {
                ui_num = Number(str_num);
            }

            if (ui_num) {
                var arr_same_xy = set_selected_row_col(obj, ui_num);

                // 合并框选对象
                arr_same_xy = arr_same_xy.concat(arr_pre_sel);

                // 设置为选中
                var arr_sel_mod = mc_mod_check(arr_same_xy);

                update_selected_mod(arr_sel_mod);
            }
        }
    }

    /************************************************************************************************
* 类型:
*    函数
* 功能:
*    画布更新 --> 更新标尺
* 参数:
*    @param { Promise<String> } obj_size 画布宽高对象; 带单位; 属性为大写;
* 返回:
*    NA
* 例子:
*    NA
* 备注:
*    obj_size{ W,""; H:"" }
* 修改:
*    1. 类型 : 创建
*       作者 : 巫昭雯
*       时间 : 2020-12-03
*       内容 : 所有代码
***********************************************************************************************/
    function update_ruler_size(obj_size) {
        if (!obj_item_checkbox_easy_mode.get_dom_val() || !b_add_screen) {
            return;
        }

        if (!obj_size) {
            return;
        }

        var obj_ruler_wrap = document.querySelector("." + str_calss_wrap);

        if (obj_ruler_wrap) {
            var obj_haed = document.getElementById(str_id_head);
            var obj_nav = document.getElementById(str_id_nav);
            var ui_zoom = get_cur_zomm();
            var ui_cur_scale = get_box_scale_multiple() / 100;
            var ui_no_scale = 1 / ui_cur_scale;

            // upate size
            if (obj_size.W) {
                var ui_bg_w = obj_canvas.offsetWidth;
                var str_w = ui_bg_w + "px";
                var str_old_w = obj_haed.style.width;

                if (str_old_w !== str_w) {
                    obj_haed.style.width = str_w;

                    var obj_svg_head = new create_side_ruler(false);
                    var ui_loop_num_x = Math.floor(ui_bg_w / (ui_easy_mode_size * ui_zoom));

                    obj_svg_head.set_row_col(1, ui_loop_num_x);
                    obj_haed.innerHTML = obj_svg_head.get_ruler_html();

                    // 文字
                    $("." + str_calss_wrap + " .head").css({
                        "transform": "scaleX(" + ui_no_scale + ")"
                    });
                }
            }

            if (obj_size.H) {
                var ui_bg_h = obj_canvas.offsetHeight;
                var str_h = ui_bg_h + "px";
                var str_old_h = obj_haed.style.width;

                if (str_old_h !== str_h) {
                    obj_nav.style.height = str_h;

                    var obj_svg_nav = new create_side_ruler();
                    var ui_loop_num_y = Math.floor(ui_bg_h / (ui_easy_mode_size * ui_zoom));

                    obj_svg_nav.set_row_col(ui_loop_num_y, 1);
                    obj_nav.innerHTML = obj_svg_nav.get_ruler_html();

                    $("." + str_calss_wrap + " .nav").css({
                        "transform": "scaleY(" + ui_no_scale + ")"
                    });
                }
            }
        }
    }

    /************************************************************************************************
* 类型:
*    函数
* 功能:
*    标尺鼠标释放事件
* 参数:
*    @param { Promise<Object> } event 鼠标事件event
* 返回:
*    NA
* 例子:
*    NA
* 备注:
*    NA
* 修改:
*    1. 类型 : 创建
*       作者 : 巫昭雯
*       时间 : 2020-12-07
*       内容 : 所有代码
************************************************************************************************/
    function mc_ruler_mouseup() {
        var obj = document.querySelector("." + str_calss_wrap);

        if (obj) {
            obj.b_down = false;
        }

        var obj_sel_ruler = obj.querySelectorAll("." + str_sel_row_col);
        var ui_len = obj_sel_ruler.length;

        // 框选对象
        var arr_mod_sel = [];

        for (var ui_i = 0; ui_i < ui_len; ui_i++) {
            var obj_ele = obj_sel_ruler[ui_i];

            if (!obj_ele) {
                continue;
            }

            var str_num = obj_ele.children[0].innerText;
            var ui_num = 0;

            if (str_num) {
                ui_num = Number(str_num);
            }

            if (ui_num) {
                var arr_mod = set_selected_row_col(obj_ele, ui_num);

                // 合并框选对象
                arr_mod_sel = arr_mod_sel.concat(arr_mod);
            }
        }

        // 设置为选中
        var arr_sel_mod = mc_mod_check(arr_mod_sel);

        update_selected_mod(arr_sel_mod);
    }

    /************************************************************************************************
* 类型:
*    函数
* 功能:
*    标尺鼠标按下
* 参数:
*    @param { Promise<Object> } event 鼠标事件event
* 返回:
*    NA
* 例子:
*    NA
* 备注:
*    NA
* 修改:
*    1. 类型 : 创建
*       作者 : 巫昭雯
*       时间 : 2020-12-07
*       内容 : 所有代码
************************************************************************************************/
    function mc_ruler_mousedown(event) {
        var e = event || window.event;
        var b_ctrl_key = e.ctrlKey;
        var str_class_name = str_sel_row_col;

        if (!b_ctrl_key) {
            $("#" + str_id_all).removeClass(str_class_name);
            // 标尺块
            var $obj_block = $(str_ruler_block_class);

            $obj_block.removeClass(str_class_name + " " + str_sel_single);

            var arr_sel_mod = mc_mod_check([]);

            update_selected_mod(arr_sel_mod);
        }
    }


    /************************************************************************************************
* 类型:
*    函数
* 功能:
*    选中模组标尺格子高亮
* 参数:
*    @param { Promise<String> } obj 标尺外框div对象
*    @param { Promise<String> } obj_idx 选中的标尺下标对象集合;
* 返回:
*    NA
* 例子:
*    NA
* 备注:
*    NA
* 修改:
*    1. 类型 : 创建
*       作者 : 巫昭雯
*       时间 : 2020-12-03
*       内容 : 所有代码
************************************************************************************************/
    function select_ruler_grid(obj, obj_idx) {
        if (!mc_util_is_object(obj_idx)) {
            return;
        }

        var obj_keys = Object.keys(obj_idx);

        if (0 === obj_keys.length) {
            return;
        }


        if (obj) {
            var arr_obj = obj.querySelectorAll("." + str_class_single_block);
            var ui_len = arr_obj.length;

            for (var ui_i = 0; ui_i < ui_len; ui_i++) {
                if ("{}" === JSON.stringify(obj_idx)) {
                    return;
                }

                var obj_ele = arr_obj[ui_i];

                if (!obj_ele) {
                    continue;
                }

                var obj_text = obj_ele.children[0];

                if (!obj_text) {
                    continue;
                }

                var ui_num = Number(obj_text.innerText);

                if (!obj_idx[ui_num]) {
                    continue;
                }

                $(obj_ele).addClass(str_sel_single);
                delete obj_idx[ui_num];
            }
        }
    }

    /************************************************************************************************
* 类型:
*    函数
* 功能:
*    框选设置点亮标尺;
* 参数:
*    @param { Promise<String> } arr_mod 框选模组
* 返回:
*    NA
* 例子:
*    NA
* 备注:
*    NA
* 修改:
*    1. 类型 : 创建
*       作者 : 巫昭雯
*       时间 : 2020-12-03
*       内容 : 所有代码
************************************************************************************************/
    function set_select_mod_ruler(arr_mod) {
        if (!b_add_screen) {
            return;
        }

        if (!obj_item_checkbox_easy_mode.get_dom_val()) {
            return;
        }

        if (!mc_util_is_array(arr_mod)) {
            return;
        }

        var str_class_name = str_sel_row_col;

        $("#" + str_id_all).removeClass(str_class_name);
        $(str_ruler_block_class).removeClass(str_class_name + " " + str_sel_single);

        var ui_len = arr_mod.length;
        var ui_size = null;
        var obj_sel_x = {};
        var obj_sel_y = {};

        for (var ui_i = 0; ui_i < ui_len; ui_i++) {
            var $obj = arr_mod[ui_i];
            var obj = $obj[0];

            if (obj) {
                if (!ui_size) {
                    ui_size = obj.offsetWidth;
                }

                var ui_top = obj.offsetTop;
                var ui_left = obj.offsetLeft;


                if (!ui_size) {
                    continue;
                }

                var ui_x = Number(ui_left / ui_size) + 1;
                var ui_y = Number(ui_top / ui_size) + 1;

                if (!obj_sel_x[ui_x]) {
                    obj_sel_x[ui_x] = true;
                }

                if (!obj_sel_y[ui_y]) {
                    obj_sel_y[ui_y] = true;
                }
            }
        }

        select_ruler_grid(document.getElementById(str_id_head), obj_sel_x);
        select_ruler_grid(document.getElementById(str_id_nav), obj_sel_y);
    }

    /************************************************************************************************
* 类型:
*    函数
* 功能:
*    标尺行选列选封装事件; 只处理一行 || 一列
* 参数:
*    @param { Promise<Object> } obj 标尺的选中行 || 列对象
*    @param { Promise<Number> } ui_num 标尺的选中行 || 列 值
* 返回:
*    @returns { Promise<Array> } 返回该行 || 列对象数组  || 返回空数组
* 例子:
*    NA
* 备注:
*    NA
* 修改:
*    1. 类型 : 创建
*       作者 : 巫昭雯
*       时间 : 2020-12-07
*       内容 : 所有代码
************************************************************************************************/
    function set_selected_row_col(obj, ui_num) {
        var arr_empty = [];

        if ("number" !== typeof ui_num) {
            return arr_empty;
        }

        if (!ui_num) {
            return arr_empty;
        }

        if (obj) {
            var str_pos = obj.getAttribute("pos");
            var ui_each_size = "";
            var str_attr = "";

            if (!str_pos) {
                return arr_empty;
            }

            if ("X" === str_pos) {
                ui_each_size = obj.offsetWidth;
                str_attr = "offsetLeft";
            } else {
                ui_each_size = obj.offsetHeight;
                str_attr = "offsetTop";
            }

            var ui_val = (ui_num - 1) * ui_each_size;
            var arr_mod = $("#mc_hlever_layout_canvas .mc_mod");
            var ui_len = arr_mod.length;

            if (0 === ui_len) {
                return arr_empty;
            }

            var arr_same_xy = [];

            for (var ui_i = 0; ui_i < ui_len; ui_i++) {
                var obj_mod = arr_mod[ui_i];

                if (obj_mod) {
                    if (obj_mod[str_attr] === ui_val) {
                        arr_same_xy.push($(obj_mod));
                    }
                }
            }

            return arr_same_xy;
        }

        return arr_empty;
    }


    /************************************************************************************************
* 类型:
*    构造函数
* 功能:
*    创建单侧标尺
* 参数:
*    @param { Promise<Boolean> } b_nav 是否为侧边; 默认 ==== true
* 返回:
*    NA
* 例子:
*    NA
* 备注:
*    NA
* 修改:
*    1. 类型 : 创建
*       作者 : 巫昭雯
*       时间 : 2020-12-08
*       内容 : 所有代码
************************************************************************************************/
    function create_side_ruler(b_nav) {
        // 定义侧边导航
        this.b_nav = true;

        if (false === b_nav) {
            this.b_nav = false;
        }

        // 设置循环次数
        var loop_num = null;

        // 设置几行几列
        this.set_row_col = function (str_row, str_col) {
            if (this.b_nav) {
                loop_num = str_row;
            } else {
                loop_num = str_col;
            }
        };

        /************************************************************************************************
* 类型:
*    函数
* 功能:
*    获取生成的单边标尺html字串
* 参数:
*    NA
* 返回：
*    @returns { Promise<String> } 生成的单边标尺html字串
* 例子：
*    NA
* 备注：
*    NA
* 修改:
*   1. 类型 : 创建
*      作者 : 巫昭雯
*       时间 : 2020-12-08
*      内容 : 所有代码
************************************************************************************************/
        this.get_ruler_html = function () {
            var ui_zoom = get_cur_zomm();

            // 设置矩阵宽高,设置矩阵x,y轴
            var rect_width = 64 * ui_zoom;
            var rect_height = 64 * ui_zoom;

            // 标尺属性
            var str_pos = "";
            var str_span_calss = "mc_ruler_text ";

            if (this.b_nav) {
                rect_width = ui_size_one_side;
                str_span_calss += " nav ";
                str_pos = "Y";
            } else {
                rect_height = ui_size_one_side;
                str_span_calss += " head ";
                str_pos = "X";
            }

            // 返回
            var str_html = "";
            var str_div_pre = "<div class='" + str_class_single_block + "' pos='" + str_pos + "' style='width:" + rect_width + "px;height:" + rect_height + "px;' onclick='click_ruler(this)'>";

            for (var idx = 0; idx < loop_num; idx++) {
                var str_val = idx + 1;
                var str_apan = "<span class='" + str_span_calss + "' style='display: inline-block;'>" + str_val + "<span>";

                str_html += str_div_pre + str_apan + "</div>";
            }

            return str_html;
        };
    }


    // **************************************** 接口 **************************************** //
    /************************************************************************************************
* 类型:
*    函数
* 功能:
*    添加构造标尺
* 参数:
*    NA
* 返回:
*    NA
* 例子:
*    NA
* 备注:
*    NA
* 修改:
*    1. 类型 : 创建
*       作者 : 巫昭雯
*       时间 : 2020-12-03
*       内容 : 所有代码
************************************************************************************************/
    this.add_coordinate_grid = function () {
        var ui_bg_w = obj_canvas.offsetWidth;
        var ui_bg_h = obj_canvas.offsetHeight;

        var ui_zoom = get_cur_zomm();

        var ui_loop_num_x = Math.floor(ui_bg_w / (ui_easy_mode_size * ui_zoom));
        var ui_loop_num_y = Math.floor(ui_bg_h / (ui_easy_mode_size * ui_zoom));

        var obj_svg_head = new create_side_ruler(false);
        var obj_svg_nav = new create_side_ruler();

        var str_div_head = "<div id='" + str_id_head + "' class='" + str_class_general + "' style='height:" + ui_size_one_side + "px;width:" + ui_bg_w + "px;top:0'></div>";
        var str_div_nav = "<div id='" + str_id_nav + "' class='" + str_class_general + "' style='width:" + ui_size_one_side + "px;height:" + ui_bg_h + "px;left:0'></div>";
        var str_div_all = "<div id='" + str_id_all + "'></div>";

        var str_html = "<div class='" + str_calss_wrap + "'>" + str_div_all + str_div_head + str_div_nav + "</div>";

        //  add dom
        $("#" + str_box_id).before(str_html);

        // save obj
        var obj_haed = document.getElementById(str_id_head);
        var obj_nav = document.getElementById(str_id_nav);
        var obj_all = document.getElementById(str_id_all);

        // 标尺点击事件
        obj_all.onclick = click_all_block;

        obj_svg_head.set_row_col(1, ui_loop_num_x);
        obj_svg_nav.set_row_col(ui_loop_num_y, 1);

        obj_box.style.top = ui_size_one_side + "px";
        obj_box.style.left = ui_size_one_side + "px";

        obj_haed.innerHTML = obj_svg_head.get_ruler_html();
        obj_nav.innerHTML = obj_svg_nav.get_ruler_html();

        update_ruler_scale();
        init_ruler_event();
        this.scroll_operation({
            scrollTop: obj_box.parentElement.scrollTop,
            scrollLeft: obj_box.parentElement.scrollLeft
        });
    };


    /************************************************************************************************
* 类型:
*    函数
* 功能:
*    移除侧边; 修改画布定位为0;0
* 参数:
*    NA
* 返回:
*    NA
* 例子:
*    NA
* 备注:
*    NA
* 修改:
*    1. 类型 : 创建
*       作者 : 巫昭雯
*       时间 : 2020-12-03
*       内容 : 所有代码
************************************************************************************************/
    this.remove_coordinate_grid = function () {
        obj_box.style.top = "0";
        obj_box.style.left = "0";

        $("." + str_calss_wrap).remove();
    };


    /************************************************************************************************
* 类型:
*    函数
* 功能:
*    滚动条监听;
* 参数:
*    @param { Promise<Object> } event 滚动条this对象
* 返回:
*    NA
* 例子:
*    NA
* 备注:
*    NA
* 修改:
*    1. 类型 : 创建
*       作者 : 巫昭雯
*       时间 : 2020-12-03
*       内容 : 所有代码
************************************************************************************************/
    this.scroll_operation = function (event) {
        if (!event) {
            return;
        }
        // 头
        $("#" + str_id_head).css({
            "top": event.scrollTop
        });

        // 侧边
        $("#" + str_id_nav).css({
            "left": event.scrollLeft
        });

        // 全部
        $("#" + str_id_all).css({
            "top": event.scrollTop,
            "left": event.scrollLeft
        });
    };


    // 更新标尺尺寸大小
    this.update_coordinate_grid = function (obj_size) {
        return update_ruler_size(obj_size);
    };

    // 缩放更新标尺
    this.zoom_coordinate_grid = function () {
        return update_ruler_scale();
    };

    // 全选
    this.select_all = function (b_all) {
        click_all_block(b_all);
    };

    // 更新选中 === 框选回调
    this.update_selected = function (arr_mod) {
        set_select_mod_ruler(arr_mod);
    };

    // 鼠标按下事件
    this.on_mouse_down = function (event) {
        mc_ruler_mousedown(event);
    };

    // 鼠标释放事件
    this.on_mouse_up = function (event) {
        mc_ruler_mouseup(event);
    };

    // 点击事件
    this.on_click_block = function (params) {
        click_event(params);
    };

    // 获取标识
    this.get_mark = function () {
        var obj = {};

        return obj;
    };

    return true;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    更新标尺大小; 与更新线条画布大小一致
 * 参数:
 *    @param { Promise<String> } obj_res_size 画布宽高对象; 带单位; 属性为大写;
 * 返回:
 *    NA
 * 例子:
 *    NA
 * 备注:
 *    obj_size{ W,""; H:"" }
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-12-08
 *       内容 : 所有代码
 ************************************************************************************************/
function mc_update_ruler_size(obj_res_size) {
    if (has_ruler_and_method("update_coordinate_grid")) {
        obj_box_coordinate_ruler.update_coordinate_grid(obj_res_size);
    }
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    鼠标按下操作指定标尺操作;
 * 参数:
 *    @param { Promise<Object> } event 鼠标事件
 * 返回:
 *    @returns { Promise<String> } 参数1 返回数据直接复制给 obj_mousedown; 为字符串时表示鼠标按下时的对象为标尺对象;
 * 例子:
 *    NA
 * 备注:
 *    主要用途: 更新主页 obj_mousedown 对象;标记鼠标按下时的对象;
 *    返回参数为三种:
 *    1. "X" === 鼠标按下时的为标尺 X轴对象
 *    2. "Y" === 鼠标按下时的为标尺 Y轴对象
 *    3. false === 鼠标按下时不为标尺对象
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-12-08
 *       内容 : 所有代码
 ************************************************************************************************/
function mc_mousedown_ruler_operation(event) {
    var res = false;

    var obj_target = event.target;
    var obj_parent = $(obj_target).parents(".mc_coorfinate_grid_wrap");

    if (0 !== obj_parent.length) {
        var obj_head = $(obj_target).parents("#mc_coordinate_grid_head");
        var obj_nav = $(obj_target).parents("#mc_coordinate_grid_nav");

        if (0 !== obj_head.length) {
            res = "X";
            if (has_ruler_and_method("on_mouse_down")) {
                obj_box_coordinate_ruler.on_mouse_down(event);
            }
        } else if (0 !== obj_nav.length) {
            res = "Y";
            if (has_ruler_and_method("on_mouse_down")) {
                obj_box_coordinate_ruler.on_mouse_down(event);
            }
        }

        return res;
    }

    return res;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    标尺块点击事件
 * 参数:
 *    @param { Promise<Object> } obj 点击的this对象
 * 返回:
 *    NA
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-12-08
 *       内容 : 所有代码
 ************************************************************************************************/
function click_ruler(obj) {
    if (has_ruler_and_method("on_click_block")) {
        obj_box_coordinate_ruler.on_click_block(obj);
    }
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    判断是否存在坐标尺并携带参数方法
 * 参数:
 *    @param { Promise<String> } str_method 需要调用的坐标尺对象的方法
 * 返回:
 *    @returns { Promise<Boolean> } true === 存在标尺并且可调用参数方法 || false === 不存在标尺对象或标尺对象不存在参数方法
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-12-08
 *       内容 : 所有代码
 ************************************************************************************************/
function has_ruler_and_method(str_method) {
    if (obj_box_coordinate_ruler && "object" === typeof obj_box_coordinate_ruler && "function" === typeof obj_box_coordinate_ruler[str_method]) {
        return true;
    }

    return false;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    更新坐标尺(选中高亮); 框选回调时更新;
 * 参数:
 *    NA
 * 返回:
 *    NA
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2021-01-19
 *       内容 : 所有代码
************************************************************************************************/
function update_coordinate_ruler_select_callback() {
    if (obj_item_checkbox_easy_mode.get_dom_val() && b_add_screen) {
        var ui_len = arr_mod_selected.length;

        if (0 === ui_len) {
            if (has_ruler_and_method("select_all")) {
                obj_box_coordinate_ruler.select_all(false);
            }
            return;
        }

        if (ui_len === $("#mc_hlever_layout_canvas .mc_mod").length) {
            if (has_ruler_and_method("select_all")) {
                obj_box_coordinate_ruler.select_all(true);
            }
        } else {
            if (has_ruler_and_method("update_selected")) {
                obj_box_coordinate_ruler.update_selected(arr_mod_selected);
            }
        }
    }
}
// **************************************** 坐标尺 **************************************** //


// **************************************** 操作记录 **************************************** //
/************************************************************************************************
 * 类型:
 *    构造函数
 * 功能:
 *    记录页面事件
 * 参数:
 *    NA
 * 返回:
 *    NA
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 徐烁超
 *       时间 : 2020-12-12
 *       内容 : 所有代码
 ************************************************************************************************/
function mc_layout_event() {
    /* ************************** 声明 ******************************** */
    // 操作列表 {type:number,before_event_ele:array,after_event_ele:array}
    var m_ary_event = [];
    var m_ui_state = -1;
    var m_obj_event_log = function (param, undo_func, redo_func) {
        this.param = !param ? {} : param;
        this.undo_func = !undo_func ? function () {
            return false;
        } : undo_func;
        this.redo_func = !redo_func ? function () {
            return false;
        } : redo_func;
    };

    /* ************************** API ******************************** */
    /**
* 记录事件
* @param {Function} undo_func 回撤事件
* @param {Function} redo_func 恢复事件
* @param {Number} obj_params 事件参数
*/
    this.event_log = function (undo_func, redo_func, obj_params) {
        m_ary_event = m_ary_event.slice(0, (m_ui_state + 1));
        m_ary_event.push(new m_obj_event_log(obj_params, undo_func, redo_func));
        m_ui_state = m_ary_event.length - 1;
        // console.log(m_ary_event, m_ui_state);
    };


    /**
* 回撤
* @returns {Function} 功能
*/
    this.undo = function () {
        return m_mc_undo();
    };

    /**
* 恢复
* @returns {Function} 功能
*/
    this.redo = function () {
        return m_mc_redo();
    };


    /* ************************** 事件 ******************************** */

    /************************************************************************************************
* 类型:
*    内部函数
* 功能:
*    根据记录回撤操作
* 参数:
*    NA
* 返回:
*    @returns {Promise<Function>} 记录的回撤事件
* 例子:
*    NA
* 备注:
*    NA
* 修改:
*    1. 类型 : 创建
*       作者 : 徐烁超
*       时间 : 2020.12.10
*       内容 : 所有代码
***********************************************************************************************/
    function m_mc_undo() {
        // 回撤事件
        var obj_event = m_ary_event[m_ui_state];

        m_ui_state--;

        if (obj_event) {
            // console.log("undo", m_ui_state);
            return obj_event.undo_func(obj_event.param, "undo");
        }

        m_ui_state++;
        // console.log("到顶了undo", m_ui_state);
        return false;
    }

    /************************************************************************************************
* 类型:
*    内部函数
* 功能:
*    根据记录恢复操作
* 参数:
*    NA
* 返回:
*    @returns {Promise<Function>} 记录的恢复事件
* 例子:
*    NA
* 备注:
*    NA
* 修改:
*    1. 类型 : 创建
*       作者 : 徐烁超
*       时间 : 2020.12.10
*       内容 : 所有代码
***********************************************************************************************/
    function m_mc_redo() {
        m_ui_state++;
        // 恢复事件
        var obj_event = m_ary_event[m_ui_state];

        if (obj_event) {
            // console.log(m_ui_state, "redo");
            return obj_event.redo_func(obj_event.param, "redo");
        }
        m_ui_state--;
        // console.log("到底了redo", m_ui_state);
        return false;
    }

    /* **************************** 功能 ****************************************** */
}


// **************************************** 回撤重做 **************************************** //
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    回撤
 * 参数:
 *    无
 * 返回：
 *    NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.14
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_lang_undo_module() {
    g_obj_event_log.undo();
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    重做
 * 参数:
 *    无
 * 返回：
 *    NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.14
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_lang_redo_module() {
    g_obj_event_log.redo();
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    操作记录undofn、redofn、param
 * 参数:
 *    @param { Promise<String> } str_type 动作类型
 *    @param { Promise<Object> } param 动作参数对象
 * 备注：
 *    须在模块整体信息、连线状态、选中队列刷新完毕后调用 (操作完成)
 *    str_type === move 移动状态
 *    str_type === connect 连线状态
 *    str_type === curd 增删替换状态
 *    str_type === transform 变换状态
 *    str_type === lock 锁定状态
 *    str_type === merge 合并状态
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     true 记录成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.14
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_operate(str_type, param) {
    if ("[object String]" !== Object.prototype.toString.call(str_type)) {
        return false;
    }
    switch (str_type) {
        case "move":
            param.obj_module_size_txt.redo = mc_get_module_size_msg();
            g_obj_event_log.event_log(mc_move_operate, mc_move_operate, param);
            break;
        case "connect":
            param.redo = JSON.parse(JSON.stringify(obj_same_hub_queue_id));
            g_obj_event_log.event_log(mc_connect_operate, mc_connect_operate, param);
            break;
        case "curd":
            param.obj_module_size_txt.redo = mc_get_module_size_msg();
            param.update_select_list.redo = mc_transform_id_data(arr_mod_selected);
            g_obj_event_log.event_log(mc_curd_operate, mc_curd_operate, param);
            break;
        case "transform":
            // param.obj_module_size_txt.redo = mc_get_module_size_msg();
            g_obj_event_log.event_log(mc_transform_operate, mc_transform_operate, param);
            break;
        case "lock":
            param.redo = mc_get_lock_module_id_data();
            g_obj_event_log.event_log(mc_lock_operate, mc_lock_operate, param);
            break;
        case "merge":
            param.obj_line_id.redo = JSON.parse(JSON.stringify(obj_same_hub_queue_id));
            param.obj_module_size_txt.redo = mc_get_module_size_msg();
            param.update_select_list.redo = mc_transform_id_data(arr_mod_selected);
            param.b_merge = true;
            g_obj_event_log.event_log(mc_curd_operate, mc_curd_operate, param);
            break;
        case "mode":
            g_obj_event_log.event_log(mc_mode_operate, mc_mode_operate, param);
            break;
        default:
            break;
    }
    // console.log(param.obj_list);
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    页面操作参数数据格式
 * 备注:
 *    1.move operate：
 *      obj_list 操作队列id
 *      undo/redo 分别为操作开始/结束时各模块位置格子数 多维数组 每项为一个模块位置
 *      obj_module_size_txt :undo/redo 整体模块大小信息更新字串 调用立即刷新无需再次计算
 *    2.connect operate：
 *      undo/redo 保存操作开始/结束连线队列
 *      其中手动连线有 manual_connect_clear undo时需重置默认状态模块id
 *    3.curd operate：
 *      add、copy：
 *          undo/redo 删除模块数组[id,,]/创建模块信息obj {id:{msg},,}
 *          obj_module_size_txt :undo/redo
 *          obj_line_id:{undo{}, redo{}}
 *      replace：
 *          b_replace = true
 *          undo/redo 替换前/替换后 {width:0,height:0,name:0,ctrlchip_name:0} wh为格子数
 *      delete：
 *          undo/redo 删除模块数据html字串_String/删除模块数组[jq,,]
 *    4.transform operate（含设置模块宽高）：
 *      obj_list
 *      undo/redo 变换前后模块变换参数数组 数组长度为1时 变换类型相同/redo
 *    5.lock operate：
 *      undo/redo 锁定前后 锁定元素id
 *    6.merge operate：
 *       同add、copy参数
 *       额外添加b_merge = true、merge_delect_id 删除队列id[id,,]
 *    7.mode：
 *       undo/redo Boolean ture 简易模式 false非简易模式
 * 参数:
 *    无
 * 返回：
 *    NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.14
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_operate_format_data() {
    // [obj_jq,,]
    this.obj_list = [];
    // [[grid_x,grid_y],,,]
    this.undo = [];
    this.redo = [];
    // 是否清屏
    this.b_clear_box = false;
    // 是否替换
    this.b_replace = false;
    // 手动连线undo时 需重置为默认卡数据
    // this.manual_connect_clear = false;
    // 是否合并
    this.b_merge = false;
    // {undo:String, redo:String}
    this.obj_module_size_txt = {
        undo: mc_get_module_size_msg(),
        redo: ""
    };
    // 更新选中队列 CURD
    this.update_select_list = {
        undo: false,
        redo: false
    };
    // 连线队列id
    this.obj_line_id = {
        undo: false,
        redo: false
    };
    // 合并删除模块id
    this.merge_delete_id = {
        undo: false,
        redo: false
    };
    // 此操作后是否进行移动（拼接变换）
    this.b_operate_after_move = false;
    // 此操作后是否需要删除模块 （组合拆分）、[删除块id]
    this.obj_operate_after = {
        undo: false,
        redo: false
    };
    // 是否操作组合元素
    this.obj_compose = {
        undo: [],
        redo: []
    };
    // 需要删除的组合块数据KEY
    this.obj_delete_compose_msg = {
        undo: [],
        redo: []
    };
    // 手动连线更新起始索引
    this.obj_manual_index = {
        undo: 0,
        redo: 0
    };
}

// 撤销替换数据格式
function mc_layout_operate_format_replace_data() {
    this.width = "";
    this.height = "";
    this.name = "";
    this.ctrlchip_name = "";
}

// move--------
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    移动操作 -撤销重做
 * 参数:
 *    @param { Promise<Object> } param 动作参数对象
 *    @param { Promise<String> } str_type 动作类型 undo/redo
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     true 操作成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.14
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_move_operate(param, str_type) {
    if ("[object Object]" !== Object.prototype.toString.call(param)) {
        return false;
    }
    if ("[object String]" !== Object.prototype.toString.call(str_type)) {
        return false;
    }
    var arr_list = param.obj_list;
    var arr_pots = param[str_type];

    if (arr_list && arr_pots && 0 !== arr_list.length && 0 !== arr_pots.length) {
        var ui_grid_w = Number(document.getElementById("mod_box_next").getAttribute("grid_w"));

        arr_list = mc_transform_obj_data(arr_list);
        if ("[object Array]" !== Object.prototype.toString.call(arr_list)) {
            return false;
        }

        for (var i = 0; i < arr_list.length; i++) {
            var obj_jq = arr_list[i];
            var arr_pot = arr_pots[i];

            if (!obj_jq || !arr_pot) {
                continue;
            }
            var obj_child = mc_get_child_pot_size(obj_jq[0], true);
            var ui_grid_x = Number(arr_pot[0]);
            var ui_grid_y = Number(arr_pot[1]);
            var str_pot = ui_grid_x + "," + ui_grid_y;
            var arr_transform = mc_analysis_transform_msg(obj_jq[0]);
            var ui_l = 0;
            var ui_t = 0;

            // 简易模式处理 ---- 获取实际格子数
            var arr_move_grid = mc_get_easy_mode_grid(obj_jq[0], ui_grid_x, ui_grid_y, true);

            if (arr_move_grid) {
                ui_grid_x = arr_move_grid[0];
                ui_grid_y = arr_move_grid[1];
            }

            if (arr_transform) {
                // 变换元素扣除偏差
                ui_l = Number(arr_transform[2]);
                ui_t = Number(arr_transform[3]);
            }

            obj_child.o_pot.innerText = str_pot;
            obj_jq.css({
                "left": ui_grid_x * ui_grid_w + ui_l + "px",
                "top": ui_grid_y * ui_grid_w + ui_t + "px"
            });
            // 更新存储数据
            mc_update_module_msg(obj_jq[0].id, str_pot, false);
            // 简易模式下更新坐标尺
            update_coordinate_ruler_select_callback();
        }
        // 更新连线
        move_block_opration(obj_same_hub_queue, arr_list);
        // 更新整体模块信息
        mc_operate_update_module_msg(param.obj_module_size_txt[str_type]);
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取简易模式下 模块实际位置格子数
 * 参数:
 *    @param { Promise<Object> } obj_js js对象
 *    @param { Promise<Number> } ui_grid_x X方向格子数
 *    @param { Promise<Number> } ui_grid_y Y方向格子数
 *    @param { Promise<Boolean> } b_really true获取实际位置格子数 false 获取显示位置格子数
 * 返回：
 *    @return { Promise<Array> }
 *     false 参数有误/不在简易模式
 *     true [ui_x,ui_y] 实际位置格子数
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.28
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_easy_mode_grid(obj_js, ui_grid_x, ui_grid_y, b_really) {
    if (!obj_item_checkbox_easy_mode.get_dom_val()) {
        return false;
    }
    if ("[object HTMLDivElement]" !== Object.prototype.toString.call(obj_js)) {
        return false;
    }
    if ("[object Number]" !== Object.prototype.toString.call(ui_grid_x)) {
        return false;
    }
    if ("[object Number]" !== Object.prototype.toString.call(ui_grid_y)) {
        return false;
    }
    // actual grid cnt = show grid cnt / mod size grid * easy size
    var ui_size_w_grid = Number(obj_js.getAttribute("mod_wg"));
    var ui_size_h_grid = Number(obj_js.getAttribute("mod_hg"));

    if ("number" === typeof ui_size_w_grid || "number" === typeof ui_size_h_grid) {
        var ui_x = 0;
        var ui_y = 0;

        if (b_really) {
            // 偏移格子数处理
            ui_grid_x = mc_util_round(ui_grid_x / ui_size_w_grid) * ui_size_w_grid;
            ui_grid_y = mc_util_round(ui_grid_y / ui_size_h_grid) * ui_size_h_grid;

            ui_x = ui_grid_x / ui_size_w_grid * ui_easy_mode_size;
            ui_y = ui_grid_y / ui_size_h_grid * ui_easy_mode_size;
        } else {
            ui_x = ui_grid_x / ui_easy_mode_size * ui_size_w_grid;
            ui_y = ui_grid_y / ui_easy_mode_size * ui_size_h_grid;
        }
        return [ui_x, ui_y];
    }
    return false;
}

// connect--------
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    连线操作 -撤销重做
 * 参数:
 *    @param { Promise<Object> } param 动作参数对象
 *    @param { Promise<String> } str_type 动作类型 undo/redo
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     true 操作成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.15
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_connect_operate(param, str_type) {
    if ("[object Object]" !== Object.prototype.toString.call(param)) {
        return false;
    }
    if ("[object String]" !== Object.prototype.toString.call(str_type)) {
        return false;
    }
    var obj_line = mc_transform_line_id(param[str_type]);
    var obj_list = $(".mc_mod");

    // 清空连线
    mc_clear_connect_operate(obj_list);
    // 刷新连线
    update_connect_queue(obj_line);
    mc_manual_connect_operate_update_param(param.obj_manual_index[str_type]);
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    初始化连线标识
 * 参数:
 *    @param { Promise<Object> } obj_list 需初始化jq对象 可能有多个
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     true 操作成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.25
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_clear_connect_operate(obj_list) {
    if ("[object Object]" !== Object.prototype.toString.call(obj_list)) {
        return false;
    }
    var obj_center = obj_list.children(".mod_hub_box").children(".mod_hub_div");

    if (b_add_screen) {
        var obj_card_idx = obj_list.children(".mc_mod_right_bto").children(".card_idx");

        // 去除模块背景色
        for (var i = 0; i < obj_list.length; i++) {
            var obj_target = obj_list.eq(i);
            var str_class_bgcolor = str_recvcard_class_name_prefix + "_" + obj_card_idx.eq(i).text() + "_" + obj_center.eq(i).text();

            obj_target.removeClass(str_class_bgcolor);
        }
        obj_card_idx.text("");
    }

    // obj_list
    obj_list.children(".mod_msg_box").children(".mod_list_idx").text("?");
    obj_center.text("?");
    obj_list.removeClass("hub_children");

    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    转换连线对象id 构造连线队列
 * 参数:
 *    @param { Promise<Object> } obj_line_id 连线对象id
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     true 操作成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.15
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_transform_line_id(obj_line_id) {
    if ("[object Object]" !== Object.prototype.toString.call(obj_line_id)) {
        return false;
    }
    var arr_key = Object.keys(obj_line_id);
    var obj_line = {};

    for (var i = 0; i < arr_key.length; i++) {
        var str_key = arr_key[i];
        var arr_id = obj_line_id[str_key];

        for (var j = 0; j < arr_id.length; j++) {
            var obj_jq = $("#" + arr_id[j]);

            if (obj_jq && 0 !== obj_jq.length) {
                if (obj_line[str_key]) {
                    obj_line[str_key].push(obj_jq);
                } else {
                    obj_line[str_key] = [obj_jq];
                }
            }
        }
    }
    return obj_line;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    存储连线id/更新中心标识/更新card_idx
 * 参数:
 *    @param { Promise<String> } str_key 当前连线队列key
 *    @param { Promise<Object> } obj_target 当前存储更新模块 js
 *    @param { Promise<String> } b_update 是否更新中心标识 可为空
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     true 操作成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.15
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_update_line_id(str_key, obj_target, b_update) {
    if ("[object String]" !== Object.prototype.toString.call(str_key)) {
        return false;
    }
    if ("[object HTMLDivElement]" !== Object.prototype.toString.call(obj_target)) {
        return false;
    }

    if (obj_same_hub_queue_id[str_key]) {
        obj_same_hub_queue_id[str_key].push(obj_target.id);
    } else {
        obj_same_hub_queue_id[str_key] = [obj_target.id];
    }

    if (b_update) {
        var mod_center = get_mod_chi_obj(obj_target.children[1].children, "mod_hub_div");

        if (mod_center) {
            if (b_add_screen) {
                var obj_card_idx = mc_get_appoint_obj($(obj_target), "card_idx");
                var arr_tip = str_key.split(":");

                // 卡下表显示
                if (obj_card_idx) {
                    obj_card_idx.innerText = arr_tip[0];
                    // 添加模块bgcolor class
                    mc_connect_operate_add_bgcolor_class(obj_target, str_recvcard_class_name_prefix + "_" + arr_tip[0] + "_" + arr_tip[1]);
                }
                // 大屏标识处理
                str_key = arr_tip[1];
            }
            mod_center.innerText = str_key;
        }
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    添加模块bgcolor class
 * 参数:
 *    @param { Promise<Object> } obj_target 当前更新模块 js
 *    @param { Promise<String> } str_class bgcolor class
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     true 操作成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.01.07
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_connect_operate_add_bgcolor_class(obj_target, str_class) {
    if ("[object HTMLDivElement]" !== Object.prototype.toString.call(obj_target)) {
        return false;
    }
    if ("[object String]" !== Object.prototype.toString.call(str_class)) {
        return false;
    }
    var str_classlist = obj_target.getAttribute("class");
    var arr_classlist = str_classlist.split(" ");
    var str_before_class = false;

    for (var i = 0; i < arr_classlist.length; i++) {
        var s_class = arr_classlist[i];


        if (-1 !== s_class.indexOf(str_recvcard_class_name_prefix)) {
            str_before_class = s_class;
            break;
        }
    }

    if (str_before_class) {
        str_classlist = str_classlist.replace(str_before_class, str_class);
    } else {
        str_classlist = str_classlist.concat(" " + str_class);
    }
    obj_target.setAttribute("class", str_classlist);
    return true;
}

// curd----------add delete replace copy
// merge---------b_merge = true && exist merge_delete_id param
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    增删替换复制操作 -撤销重做
 * 参数:
 *    @param { Promise<Object> } param 动作参数对象
 *    @param { Promise<String> } str_type 动作类型 undo/redo
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     true 操作成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.25
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_curd_operate(param, str_type) {
    if ("[object Object]" !== Object.prototype.toString.call(param)) {
        return false;
    }
    if ("[object String]" !== Object.prototype.toString.call(str_type)) {
        return false;
    }

    var curd_param = param[str_type];

    if (!curd_param) {
        return false;
    }
    var obj_line_id = param.obj_line_id[str_type];
    var str_module_msg = param.obj_module_size_txt[str_type];
    var b_replace = param.b_replace;
    var obj_select_list = param.update_select_list;

    var arr_select_list = false;
    var arr_compose = param.obj_compose[str_type];
    var arr_delect_compose_msg = param.obj_delete_compose_msg[str_type];
    var arr_delect_module = param.obj_operate_after[str_type];


    if ("[object Object]" === Object.prototype.toString.call(obj_select_list)) {
        arr_select_list = obj_select_list[str_type];
    }

    // add curd_param = {id:{create msg},,} ;create module、update line、select module、module size; params: undo/redo obj_module_size_txt obj_line_id update_select_list
    // replace curd_param = {id:{replace} msg},,} update select module、replace module、line、module size; params: undo/redo obj_module_size_txt update_select_list
    // delete curd_param = [str_id,,] delect moudule、update line、select module、module size; params: undo/redo obj_module_size_txt obj_line_id update_select_list


    if ("[object Object]" === Object.prototype.toString.call(curd_param)) {
        var arr_keys = Object.keys(curd_param);
        var str_id = "";
        var obj_msg = null;

        if (b_replace) {
            // replace
            for (var j = 0; j < arr_keys.length; j++) {
                str_id = arr_keys[j];
                obj_msg = curd_param[str_id];

                mc_operate_replace(str_id, obj_msg);
            }
        } else {
            // 清屏后添加
            if (param.b_clear_box) {
                clear_box_canvas();
            }
            var str_module_html = "";
            var str_compose_html = "";
            var obj_module_line_id = {};

            // add
            for (var i = 0; i < arr_keys.length; i++) {
                str_id = arr_keys[i];
                obj_msg = curd_param[str_id];
                if (arr_compose[i]) {
                    // 添加组合元素1
                    str_compose_html += mc_get_compose_html(obj_msg, str_id).str_html;
                } else {
                    if (arr_delect_compose_msg[i]) {
                        // 删除组合块数据
                        mc_delete_compose_msg(arr_delect_compose_msg[i]);
                    }
                    var obj_module_msg = add_mod_one(obj_msg, str_id, true);

                    str_module_html += obj_module_msg.str_html;
                    obj_module_line_id = obj_module_msg.obj_module_line_id;
                }
            }
            add_mod_html(str_module_html, obj_module_line_id);
            // 添加组合元素2
            if (0 !== str_compose_html.length) {
                $(".mc_mod_box").prepend(str_compose_html);
            }
        }
        // 简易模式处理
        mc_set_easy_mode();
    }

    if ("[object Array]" === Object.prototype.toString.call(curd_param)) {
        // delete
        for (var idx = 0; idx < curd_param.length; idx++) {
            var obj_jq = $("#" + curd_param[idx]);

            if (obj_jq) {
                obj_jq.remove();
            }
            if (arr_delect_compose_msg[idx]) {
                // 删除组合块数据
                mc_delete_compose_msg(arr_delect_compose_msg[idx]);
            }
        }
    }

    // 组合拆分删除对应块
    if ("[object Array]" === Object.prototype.toString.call(arr_delect_module)) {
        for (var index = 0; index < arr_delect_module.length; index++) {
            $("#" + arr_delect_module[index]).remove();
        }
    }

    // merge delect
    mc_merge_delect_operate(param, str_type);

    // update selected list
    if (arr_select_list) {
        // id数组转换为对象
        arr_select_list = mc_transform_obj_data(arr_select_list);
        // 更新选中
        update_select_data(arr_select_list);
    }

    // 简易模式下更新坐标尺
    update_coordinate_ruler_select_callback();
    // 更新整体模块数量
    mc_update_module_size();

    // update line
    if (obj_line_id) {
        var obj_line = mc_transform_line_id(obj_line_id);

        if (obj_line) {
            update_connect_queue(obj_line);
        }
    } else {
        move_block_opration(obj_same_hub_queue, arr_select_list);
    }

    // update module size
    if (str_module_msg) {
        mc_operate_update_module_msg(param.obj_module_size_txt[str_type]);
    }

    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    简易模式下修改模组大小偏移
 * 参数:
 *    无
 * 返回：
 *    NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.28
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_set_easy_mode() {
    if (obj_item_checkbox_easy_mode.get_dom_val()) {
        set_easy_mode(true);
    }
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    合并状态下 删除模块
 * 参数:
 *    @param { Promise<Object> } param 动作参数对象
 *    @param { Promise<String> } str_type 动作类型 undo/redo
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     true 操作成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.26
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_merge_delect_operate(param, str_type) {
    if ("[object Object]" !== Object.prototype.toString.call(param)) {
        return false;
    }
    if ("[object String]" !== Object.prototype.toString.call(str_type)) {
        return false;
    }
    if (!param.b_merge) {
        return false;
    }
    var obj_delect_id = param.merge_delete_id;
    var arr_delect_id = obj_delect_id[str_type];

    if ("[object Array]" === Object.prototype.toString.call(arr_delect_id)) {
        for (var idx = 0; idx < arr_delect_id.length; idx++) {
            var obj_jq = $("#" + arr_delect_id[idx]);

            if (obj_jq) {
                obj_jq.remove();
            }
        }
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取构建模块数据
 * 参数:
 *    @param { Promise<Array> } arr_select 选中jq对象数组
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     obj_msg {id:{msg},,,}
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_create_module_msg(arr_select) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_select)) {
        return false;
    }
    // {id,{msg},,}
    var obj_msg = {};

    for (var i = 0; i < arr_select.length; i++) {
        var obj_js = arr_select[i][0];

        if (!obj_js) {
            continue;
        }
        var obj_child_msg = mc_get_child_pot_size(obj_js);
        var arr_pot = obj_child_msg.str_pot.split(",");
        var obj_format_data = new format_mod_data();
        var obj_list_idx = obj_child_msg.o_pot.nextSibling;
        var str_center = arr_select[i].children(".mod_hub_box").children(".mod_hub_div").text();
        var obj_show_name = arr_select[i].children(".mod_msg_box").children(".mod_show_name");

        obj_format_data.width = obj_js.getAttribute("mod_wg");
        obj_format_data.height = obj_js.getAttribute("mod_hg");
        obj_format_data.left = arr_pot[0];
        obj_format_data.top = arr_pot[1];
        obj_format_data.val = str_center;
        obj_format_data.name = obj_js.getAttribute("mod_id");
        if (obj_show_name) {
            obj_format_data.show_name = obj_show_name.text();
        }

        // list idx
        if (obj_list_idx) {
            obj_format_data.list_idx = obj_list_idx.innerText;
        }
        if (b_add_screen) {
            var obj_chip = obj_child_msg.o_size.previousSibling;
            var obj_card_idx = mc_get_appoint_obj(arr_select[i], "card_idx", true);

            // chip
            if (obj_chip) {
                obj_format_data.ctrlchip_name = obj_chip.innerText;
            }

            // card idx
            if (obj_card_idx) {
                var str_card_idx = obj_card_idx.text();

                if (str_card_idx && 0 !== str_card_idx.length) {
                    obj_format_data.card_idx = str_card_idx;
                    // css rule
                    obj_format_data.class_name = str_recvcard_class_name_prefix + "_" + str_card_idx + "_" + str_center;
                } else {
                    obj_format_data.card_idx = "";
                }
            }
        }
        // transform
        // [[W,H,Lc,Tc], "angle", [缩放倍数X, 缩放倍数Y], "镜像"]
        var arr_transform = mc_analysis_transform_msg(obj_js, "all", true);


        if (arr_transform && 4 === arr_transform.length && 2 === arr_transform[2].length) {
            // param ["X缩放","Y缩放","旋转角度","镜像类型"]
            obj_format_data.transform_param = [arr_transform[2][0], arr_transform[2][1], arr_transform[1], arr_transform[3]];
        }
        obj_msg[obj_js.id] = obj_format_data;
    }
    return obj_msg;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取替换模块数据
 * 参数:
 *    @param { Promise<Array> } arr_select 选中jq对象数组
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     obj_msg {id:{msg},,,}
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_replace_module_msg(arr_select) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_select)) {
        return false;
    }
    // {id,{msg},,}
    var obj_msg = {};

    for (var i = 0; i < arr_select.length; i++) {
        var obj_js = arr_select[i][0];
        var obj_format_data = new mc_layout_operate_format_replace_data();

        obj_format_data.width = obj_js.getAttribute("mod_wg");
        obj_format_data.height = obj_js.getAttribute("mod_hg");
        obj_format_data.name = obj_js.getAttribute("mod_id");
        if (b_add_screen) {
            var obj_chip = arr_select[i].children(".mod_msg_box").children(".chip_name");

            if (obj_chip) {
                obj_format_data.ctrlchip_name = obj_chip.text();
            }
        }
        obj_msg[obj_js.id] = obj_format_data;
    }
    return obj_msg;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    选中模块对象数组转换为id数组
 * 参数:
 *    @param { Promise<Array> } arr_select 选中jq对象数组
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     arr_id [str_id,,]
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_transform_id_data(arr_select) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_select)) {
        return false;
    }
    var arr_id = [];

    for (var i = 0; i < arr_select.length; i++) {
        var obj_js = arr_select[i][0];

        if (obj_js) {
            arr_id.push(arr_select[i][0].id);
        }
    }
    return arr_id;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    id数组转化为jq对象数组
 * 参数:
 *    @param { Promise<Array> } arr_select 选中jq对象数组
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     arr_result [obj_jq,,]
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_transform_obj_data(arr_select) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_select)) {
        return false;
    }
    var arr_result = [];

    for (var i = 0; i < arr_select.length; i++) {
        var obj_jq = $("#" + arr_select[i]);

        if (obj_jq) {
            arr_result.push(obj_jq);
        }
    }
    return arr_result;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    更新选中队列
 * 参数:
 *    @param { Promise<Array> } ary_list 选中jq对象数组
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     true 设置成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.16
 *      内容 : 所有代码
 ************************************************************************************************/
function update_select_data(ary_list) {
    if ("[object Array]" !== Object.prototype.toString.call(ary_list)) {
        return false;
    }
    // update control data
    mc_mod_uncheck(arr_mod_selected);
    // update page data
    operate_update_select(ary_list);

    for (var i_select = 0; i_select < ary_list.length; i_select++) {
        mc_select_module(ary_list[i_select][0]);
    }
    mc_clear_zindex();
    mc_select_item_add_zindex(ary_list);
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    撤销操作-替换 逐个替换
 * 参数:
 *    @param { Promise<String> } str_id 替换模块id
 *    @param { Promise<Object> } obj_msg 替换数据对象
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     true 设置成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_operate_replace(str_id, obj_msg) {
    if ("[object String]" !== Object.prototype.toString.call(str_id)) {
        return false;
    }
    if ("[object Object]" !== Object.prototype.toString.call(obj_msg)) {
        return false;
    }

    var ui_grid = Number(document.getElementById("mod_box_next").getAttribute("grid_w"));
    var ui_width = Number(obj_msg.width);
    var ui_height = Number(obj_msg.height);
    var str_mod_id = obj_msg.name;
    var ctrlchip_name = obj_msg.ctrlchip_name;

    var i_width = ui_grid * ui_width;
    var i_height = ui_grid * ui_height;
    var str_img_url = "";
    // var str_no_select = "";

    if (!b_add_screen) {
        var obj_canvasbg = mc_judge_create_canvasbg(str_mod_id, String(ui_grid));

        if ("[object Object]" === Object.prototype.toString.call(obj_canvasbg)) {
            // str_no_select = obj_canvasbg.img_url;
            str_img_url = obj_canvasbg.select_url;
        } else {
            // eslint-disable-next-line no-undef
            var ary_pix = mc_layout_get_mod_dot_location(str_mod_id, ARY_MOD_DATA);

            // str_no_select = set_mod_bgimg(i_width, i_height, ary_pix)[0];
            str_img_url = set_mod_bgimg(i_width, i_height, ary_pix)[1];
        }
    }

    var o_mod = $("#" + str_id);

    if (!o_mod) {
        return false;
    }

    if (b_add_screen && "string" === typeof ctrlchip_name) {
        o_mod.children(".mod_msg_box").children(".chip_name").text(ctrlchip_name);
    }
    o_mod.css({
        "width": i_width + "px",
        "height": i_height + "px"
    }).attr({
        "mod_id": str_mod_id,
        "mod_wg": ui_width,
        "mod_hg": ui_height
    });
    o_mod.children(".mod_msg_box").children(".mod_size").text(ui_width + "X" + ui_height);
    if ("" !== str_img_url) {
        o_mod.css("background-image", "url(" + str_img_url + ")");
    }
    // 更新模块信息
    mc_update_module_msg(o_mod[0].id, false, ui_width + "X" + ui_height);
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取选中模块数组格式数据
 * 参数:
 *    无
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     arr_result [obj_jq,,]
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_format_module_data() {
    var obj_list = document.getElementsByClassName("mc_mod");
    var arr_result = [];

    for (var i = 0; i < obj_list.length; i++) {
        arr_result.push($(obj_list[i]));
    }
    return arr_result;
}

// transform-----------save 操作对象obj_list、undo/redo变换参数对象数组集
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    变换操作（含设置模块大小） -撤销重做
 * 参数:
 *    @param { Promise<Object> } param 动作参数对象
 *    @param { Promise<String> } str_type 动作类型 undo/redo
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     true 操作成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.25
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_transform_operate(param, str_type) {
    if ("[object Object]" !== Object.prototype.toString.call(param)) {
        return false;
    }
    if ("[object String]" !== Object.prototype.toString.call(str_type)) {
        return false;
    }
    var arr_list = param.obj_list;
    // 每个元素变换对象参数 undo时长度为1
    var arr_transform_param = param[str_type];

    if (arr_list && 0 !== arr_list.length && arr_transform_param && 0 !== arr_transform_param.length) {
        arr_list = mc_transform_obj_data(arr_list);

        if (obj_item_checkbox_easy_mode.get_dom_val()) {
            // 简易模式下处理
            mc_easy_mode_reset_transform_param(arr_list, arr_transform_param);
            return true;
        }

        // 不同变换类型判断
        if (1 === arr_transform_param.length) {
            mc_transform_operate_apply(arr_list, arr_transform_param[0], true, true);
        } else {
            for (var i = 0; i < arr_transform_param.length; i++) {
                mc_transform_operate_apply([arr_list[i]], arr_transform_param[i], true, true);
            }
        }
        // 更新连线
        move_block_opration(obj_same_hub_queue, arr_list);
    }
    if (param.b_operate_after_move) {
        var after_param = JSON.parse(JSON.stringify(param));

        after_param.undo = after_param.obj_operate_after.undo;
        after_param.redo = after_param.obj_operate_after.redo;
        mc_move_operate(after_param, str_type);
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    简易模式下回撤重做 更新str_trans属性
 * 参数:
 *    @param { Promise<Array> } arr_jq_list 更新属性jq对象数组
 *    @param { Promise<Array> } arr_transform_param 变换参数对象数组
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     true 更新成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.29
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_easy_mode_reset_transform_param(arr_jq_list, arr_transform_param) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_jq_list)) {
        return false;
    }
    if ("[object Array]" !== Object.prototype.toString.call(arr_transform_param)) {
        return false;
    }
    if (!obj_item_checkbox_easy_mode.get_dom_val()) {
        return false;
    }
    if (1 === arr_transform_param.length) {
        for (var i = 0; i < arr_jq_list.length; i++) {
            var obj_js = arr_jq_list[i][0];

            if (obj_js) {
                obj_js.setAttribute("str_trans", JSON.stringify(arr_transform_param[0]));
            }
        }
    } else {
        for (var j = 0; j < arr_jq_list.length; j++) {
            var obj_target = arr_jq_list[j][0];

            if (obj_target) {
                obj_target.setAttribute("str_trans", JSON.stringify(arr_transform_param[j]));
            }
        }
    }
    return true;
}

// 变换应用参数格式
function mc_layout_operate_format_transform_data() {
    this.MC_LANG_X_DIRECTION = {
        "val": "1.0"
    };
    this.MC_LANG_Y_DIRECTION = {
        "val": "1.0"
    };
    this.MC_LANG_ROTATION_ANGLE = {
        "val": "0"
    };
    this.MC_LANG_MIRROR_IMAGE = {
        "val": "0"
    };
    this.MC_LANG_HORZ_HEAD = {
        "val": "0"
    };
    this.MC_LANG_HORZ_RAIL = {
        "val": "0"
    };
    this.MC_LANG_VERTICAL_HEAD = {
        "val": "0"
    };
    this.MC_LANG_VERTICAL_TAIL = {
        "val": "0"
    };
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    构造变换应用参数 (变换前)
 * 参数:
 *    @param { Promise<Array> } arr_select 选中jq对象数组
 *    @param { Promise<Array> } arr_cut 裁剪数据
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     arr_result 变换参数对象数组
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.25
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_construct_transform_apply_param(arr_select, arr_cut) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_select)) {
        return false;
    }
    // true 只有一种变换类型
    var b_one_type = true;
    var obj_first_data = null;
    var arr_result = [];

    for (var i = 0; i < arr_select.length; i++) {
        var obj_js = arr_select[i][0];
        var obj_param = new mc_layout_operate_format_transform_data();
        //  [[W,H,Lc,Tc], "angle", [缩放倍数X, 缩放倍数Y], "镜像"]
        var arr_transform_msg = mc_analysis_transform_msg(obj_js, "all");

        var obj_msg = mc_get_child_pot_size(obj_js);
        var arr_size = obj_msg.str_size.split("X");

        if (0 >= Number(arr_size[0]) + arr_cut[0] + arr_cut[1]) {
            obj_param.MC_LANG_HORZ_HEAD = { "val": 0 };
            obj_param.MC_LANG_HORZ_RAIL = { "val": 0 };
        } else {
            obj_param.MC_LANG_HORZ_HEAD = { "val": arr_cut[0] };
            obj_param.MC_LANG_HORZ_RAIL = { "val": arr_cut[1] };
        }
        if (0 >= Number(arr_size[1]) + arr_cut[2] + arr_cut[3]) {
            obj_param.MC_LANG_VERTICAL_HEAD = { "val": 0 };
            obj_param.MC_LANG_VERTICAL_TAIL = { "val": 0 };
        } else {
            obj_param.MC_LANG_VERTICAL_HEAD = { "val": arr_cut[2] };
            obj_param.MC_LANG_VERTICAL_TAIL = { "val": arr_cut[3] };
        }
        if (arr_transform_msg && 4 >= arr_transform_msg.length) {
            var arr_scale = arr_transform_msg[2];

            obj_param.MC_LANG_ROTATION_ANGLE.val = Number(arr_transform_msg[1]);
            obj_param.MC_LANG_MIRROR_IMAGE.val = Number(arr_transform_msg[3]);
            if (arr_scale && 2 === arr_scale.length) {
                obj_param.MC_LANG_X_DIRECTION.val = Number(arr_scale[0]);
                obj_param.MC_LANG_Y_DIRECTION.val = Number(arr_scale[1]);
            }
            // 保存对比数据
            if (!obj_first_data) {
                obj_first_data = obj_param;
            } else if (obj_first_data !== obj_param) {
                b_one_type = false;
            }
        }
        arr_result.push(obj_param);
    }

    // 只有一种变换类型
    if (b_one_type) {
        arr_result = [arr_result[0]];
    }
    return arr_result;
}

// lock----------------
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    锁定操作 -撤销重做
 * 参数:
 *    @param { Promise<Object> } param 动作参数对象
 *    @param { Promise<String> } str_type 动作类型 undo/redo
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     true 操作成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.25
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_lock_operate(param, str_type) {
    if ("[object Object]" !== Object.prototype.toString.call(param)) {
        return false;
    }
    if ("[object String]" !== Object.prototype.toString.call(str_type)) {
        return false;
    }
    var arr_lock_list = param[str_type];

    if ("[object Array]" === Object.prototype.toString.call(arr_lock_list)) {
        arr_lock_list = mc_transform_obj_data(arr_lock_list);
        $(".mc_lock").removeClass("mc_lock");

        for (var i = 0; i < arr_lock_list.length; i++) {
            arr_lock_list[i].addClass("mc_lock");
        }
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取当前锁定元素id数组
 * 参数:
 *    无
 * 返回：
 *    @return { Promise<Array> }
 *     arr_result 获取当前锁定元素id数组
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.25
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_lock_module_id_data() {
    var arr_result = [];
    var obj_list = document.getElementsByClassName("mc_lock");

    for (var i = 0; i < obj_list.length; i++) {
        arr_result.push(obj_list[i].id);
    }
    return arr_result;
}

// mode---------------
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    切换简易模式操作 -撤销重做
 * 参数:
 *    @param { Promise<Object> } param 动作参数对象
 *    @param { Promise<String> } str_type 动作类型 undo/redo
 * 返回：
 *    @return { Promise<Boolean> }
 *     false 参数有误
 *     true 操作成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2020.12.28
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_mode_operate(param, str_type) {
    if ("[object Object]" !== Object.prototype.toString.call(param)) {
        return false;
    }
    if ("[object String]" !== Object.prototype.toString.call(str_type)) {
        return false;
    }
    var b_easy_mode = param[str_type];

    update_opt_easy_mode(false, b_easy_mode, true);
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    缓存大屏连接箱体发送数据
 * 参数:
 *    无
 * 返回：
 *    NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.12.18
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_layout_cache_box() {
    var m_ary_box_data = [];
    var m_ary_cache = [];
    var m_ary_send_data = [];
    var m_ui_get_tpl = -1;

    /**
* 存入模板箱体数据
* @param {Array} ary_box_data 模板箱体数据
*/
    this.set_box_tpl = function (ary_box_data) {
        // debugger;
        m_ary_cache = [];
        m_ary_box_data = [];

        for (var idx_box = 0; idx_box < ary_box_data.length; idx_box++) {
            var obj_data = ary_box_data[idx_box];
            var obj_ui_box = new mc_ui_box();
            var ary_trans_val = obj_data.data.mc_util_get_trans();

            obj_ui_box.mc_util_set_trans(ary_trans_val);
            obj_ui_box.mc_util_set_gamma_val(obj_data.data.mc_util_get_gamma_val());
            obj_ui_box.mc_util_set_param(obj_data.data.mc_util_get_param());
            obj_ui_box.mc_util_set_resul(obj_data.data.mc_util_get_resul());
            obj_ui_box.mc_util_set_disp_reg(obj_data.data.mc_util_get_disp_reg());
            obj_ui_box.mc_util_set_disp_reg_list(obj_data.data.mc_util_get_disp_reg_list());
            obj_ui_box.mc_util_set_scan_reg(obj_data.data.mc_util_get_scan_reg());
            obj_ui_box.mc_util_set_scan_reg_list(obj_data.data.mc_util_get_scan_reg_list());

            obj_ui_box.mc_util_set_ui_box_msg(obj_data.data.mc_util_get_ui_box_msg());

            var ary_box_size = obj_data.data.mc_util_get_box_size();

            obj_ui_box.mc_util_set_box_size(ary_box_size[0], ary_box_size[1]);
            obj_ui_box.mc_util_set_correct_msg(obj_data.data.mc_util_get_correct_msg());
            obj_ui_box.mc_util_set_restore(obj_data.data.mc_util_get_restore());
            var obj_sdk_recvcard_param = obj_data.data.mc_util_get_device_data();

            obj_ui_box.mc_util_set_device_data(obj_sdk_recvcard_param);
            if (obj_data.data.mc_util_get_box_is_set()) {
                obj_ui_box.mc_util_set_box_is_set();
            }
            if (!obj_data.data.mc_util_get_box_change()) {
                obj_ui_box.mc_util_set_box_change();
            }


            m_ary_box_data.push({
                name: obj_data.name,
                data: obj_ui_box
            });
            m_ary_cache.push({
                name: obj_data.name,
                data: obj_ui_box,
                mirror: ary_trans_val[0],
                rotation: ary_trans_val[1],
                scale: ary_trans_val[2],
                cut: ary_trans_val[4] || "0,0,0,0"
            });
        }
    };

    /**
* 获取指定箱体参数
* @param {String} box_name 箱体名称
* @param {String} mirror 箱体镜像信息
* @param {String} rotation 箱体旋转信息
* @param {String} scale 箱体缩放信息
* @returns {Array} 指定箱体数据
* @param {String} cut 箱体裁剪信息
*/
    this.get_trans_box = function (box_name, mirror, rotation, scale, cut) {
        if (0 === m_ary_box_data.length) {
            return false;
        }
        var b_is_set_edit = false;

        if (!cut) {
            cut = "0,0,0,0";
        }

        mirror = mirror.replace(/\(|\)/g, "").replace(/:/g, ",");
        rotation = rotation.replace(/\(|\)/g, "").replace(/:/g, ",");
        scale = scale.replace(/\(|\)/g, "").replace(/:/g, ",");
        cut = cut.replace(/\(|\)/g, "").replace(/:/g, ",");

        m_ary_send_data = [];
        for (var idx_cache = 0; idx_cache < m_ary_cache.length; idx_cache++) {
            var obj_box_cache = m_ary_cache[idx_cache];

            if (
                box_name === obj_box_cache.name &&
                mc_contrast_param(mirror, obj_box_cache.mirror) &&
                mc_contrast_param(rotation, obj_box_cache.rotation) &&
                mc_contrast_param(scale, obj_box_cache.scale) &&
                mc_contrast_param(cut, obj_box_cache.cut)
            ) {
                m_ui_get_tpl = idx_cache;
                var obj_cache_edit = obj_box_cache.data.mc_util_get_ui_box_msg();

                if (
                    !obj_cache_edit.edit_val ||
                    !obj_cache_edit.edit_val.ary_child_pin
                ) {
                    b_is_set_edit = true;
                }

                return [[obj_box_cache], true, false, b_is_set_edit];
            }
        }
        var obj_data = mc_get_box_by_name(m_ary_cache);
        var b_is_get_param = false;

        if (!obj_data) {
            m_ui_get_tpl = -1;
            b_is_get_param = true;
            obj_data = mc_get_box_by_name(m_ary_box_data);
        }
        m_ary_send_data = [obj_data];

        var obj_send_data = obj_data.data.mc_util_get_ui_box_msg();

        if (
            !obj_send_data.edit_val ||
            !obj_send_data.edit_val.ary_child_pin
        ) {
            b_is_set_edit = true;
        }
        return [m_ary_send_data, false, b_is_get_param, b_is_set_edit];

        function mc_get_box_by_name(ary_seach) {
            for (var idx_tpl = 0; idx_tpl < ary_seach.length; idx_tpl++) {
                var obj_box_tpl = ary_seach[idx_tpl];

                if (obj_box_tpl.name === box_name) {
                    var obj_ui_box = new mc_ui_box();

                    obj_ui_box.mc_util_set_trans([mirror, rotation, scale, false, cut]);
                    obj_ui_box.mc_util_set_gamma_val(obj_box_tpl.data.mc_util_get_gamma_val());
                    obj_ui_box.mc_util_set_param(obj_box_tpl.data.mc_util_get_param());
                    obj_ui_box.mc_util_set_resul(obj_box_tpl.data.mc_util_get_resul());
                    obj_ui_box.mc_util_set_disp_reg(obj_box_tpl.data.mc_util_get_disp_reg());
                    obj_ui_box.mc_util_set_disp_reg_list(obj_box_tpl.data.mc_util_get_disp_reg_list());
                    obj_ui_box.mc_util_set_scan_reg(obj_box_tpl.data.mc_util_get_scan_reg());
                    obj_ui_box.mc_util_set_scan_reg_list(obj_box_tpl.data.mc_util_get_scan_reg_list());
                    obj_ui_box.mc_util_set_ui_box_msg(obj_box_tpl.data.mc_util_get_ui_box_msg());

                    var ary_box_size = obj_box_tpl.data.mc_util_get_box_size();

                    obj_ui_box.mc_util_set_box_size(ary_box_size[0], ary_box_size[1]);
                    obj_ui_box.mc_util_set_correct_msg(obj_box_tpl.data.mc_util_get_correct_msg());
                    obj_ui_box.mc_util_set_restore(obj_box_tpl.data.mc_util_get_restore());

                    m_ui_get_tpl = idx_tpl;

                    return {
                        name: obj_box_tpl.name,
                        data: obj_ui_box,
                        mirror: mirror,
                        rotation: rotation,
                        scale: scale,
                        cut: cut
                    };
                }
            }
            return false;
        }
    };

    /**
* 缓存当前发送数据
* @param {Boolean} b_is_set_edit 是否设置了edit判断
*/
    this.cache_box = function (b_is_set_edit) {
        if (
            -1 !== m_ui_get_tpl &&
            b_is_set_edit &&
            m_ary_cache.length > m_ui_get_tpl
        ) {
            var obj_send_box_data = m_ary_cache[m_ui_get_tpl].data.mc_util_get_ui_box_msg();
            var obj_get_edit_val = obj_send_box_data.edit_val;
            var str_send_box_ctrl = obj_send_box_data.ctrlchip_name;

            for (var idx_edit = 0; idx_edit < m_ary_cache.length; idx_edit++) {
                var obj_data = m_ary_cache[idx_edit].data;

                var obj_data_msg = obj_data.mc_util_get_ui_box_msg();

                if (
                    (!obj_data_msg.edit_val || !obj_data_msg.edit_val.ary_child_pin) &&
                    obj_data_msg.ctrlchip_name === str_send_box_ctrl
                ) {
                    obj_data_msg.edit_val = obj_get_edit_val;
                }
            }
        }
        if (0 === m_ary_send_data.length) {
            return;
        }
        // var obj_send_data = m_ary_send_data[0].data;
        // var obj_sdk_recvcard_param = obj_send_data.mc_util_get_device_data();
        // var ui_param_cnt = obj_sdk_recvcard_param.get_param_cnt();

        // if (0 >= ui_param_cnt) {
        //     m_ary_send_data = [];
        //     return;
        // }
        m_ary_cache.push(m_ary_send_data[0]);
        m_ary_send_data = [];
        if (600 === m_ary_cache.length) {
            m_ary_cache = m_ary_cache.slice(299, 600);
        }
    };

    /**
*
* @param {String} str_param_1 对比参数1
* @param {String} str_param_2 对比参数2
* @returns {Boolean} 两个参数内容是否相同
*/
    function mc_contrast_param(str_param_1, str_param_2) {
        if (
            -1 === str_param_1.indexOf(",") &&
            -1 === str_param_2.indexOf(",")
        ) {
            return str_param_2 === str_param_1;
        }

        var ary_param_1 = str_param_1.split(",");
        var ary_param_2 = str_param_2.split(",");

        if (ary_param_1.length !== ary_param_2.length) {
            return false;
        }

        var b_is_same = true;

        for (var idx_param = 0; idx_param < ary_param_1.length; idx_param++) {
            var ui_param_1 = Number(ary_param_1[idx_param]);
            var ui_param_2 = Number(ary_param_2[idx_param]);

            if (ui_param_1 !== ui_param_2) {
                b_is_same = false;
                break;
            }
        }
        return b_is_same;
    }
}


// **************************************** 框选联动数据 **************************************** //
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    框选联动数据 --- 更新连线弹窗端口数据
 * 参数:
 *    @param { Promise<Array> } obj_page 子窗口页面window对象
 *    @param { Promise<Array> } arr_mod 框选模组
 * 返回:
 *    NA
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-12-22
 *       内容 : 所有代码
 ************************************************************************************************/
function mc_selectd_link_data_port(obj_page, arr_mod) {
    if (!obj_page.box_sel_link_data) {
        return;
    }

    if ("function" !== typeof obj_page.box_sel_link_data) {
        return;
    }

    var obj_first = null;
    var str_key = "";
    var ui_len = arr_mod.length;

    // get key
    for (var ui_i = 0; ui_i < ui_len; ui_i++) {
        var ele = arr_mod[ui_i];

        if (0 === ele.length) {
            continue;
        }

        var obj_key = ele.children(".mod_hub_box").children(".mod_hub_div");

        if (0 === obj_key.length) {
            continue;
        }

        str_key = obj_key.text();

        if (str_key === str_mod_init_val) {
            continue;
        }

        str_key = mc_get_line_key(b_add_screen, ele, str_key);
        obj_first = ele;
        break;
    }

    if (obj_first && str_key) {
        obj_page.box_sel_link_data(obj_first, str_key, b_add_screen);
    }

    return;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    更新json串值 (连线弹窗端口json串)
 * 参数:
 *    @param { Promise<String> } str json串
 *    @param { Promise<Object> } obj 更新key(name_id)-val 键值对
 * 返回:
 *    @returns { Promise<String> } 更新后的json串 || false === obj keys length === 0
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-12-22
 *       内容 : 所有代码
 ************************************************************************************************/
function mc_update_setcard_menu_json(str, obj) {
    if (!str || !obj) {
        return false;
    }

    var arr_keys = Object.keys(obj);
    var ui_len = arr_keys.length;

    if (0 === ui_len) {
        return false;
    }

    var obj_sdk_param = new mc_sdk_param();

    obj_sdk_param.set_json(str);

    for (var ui_i = 0; ui_i < ui_len; ui_i++) {
        var str_name_id = arr_keys[ui_i];
        var str_val = obj[str_name_id];

        obj_sdk_param.set_param_value(str_name_id, str_val);
    }

    var str_new_json = obj_sdk_param.get_json();

    return str_new_json;
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取线条key值的val(除去字母)
 * 参数:
 *    @param { Promise<String> } str_key 连线key
 *    @param { Promise<String> } b_screen  是否是大屏
 * 返回:
 *    @returns { Promise<String> } 模组时返回hub口的值  || 为大屏时返回所有卡的数组;
 * 例子:
 *    NA
 * 备注:
 *    返回类型为数组时:
 *    [ 发送卡, 发送卡输出口, hub卡, hub卡输出口 ]
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-12-22
 *       内容 : 所有代码
 ************************************************************************************************/
function mc_get_line_key_val(str_key, b_screen) {
    if ("string" !== typeof str_key) {
        return false;
    }

    if (!str_key.trim() || str_mod_init_val === str_key.trim()) {
        return str_key;
    }

    if (!b_screen) {
        return str_key.replace("J", "");
    }

    var str_key_val = mc_replace_line_key_letters(str_key);
    var arr_val = str_key_val.split(":");

    if (4 > arr_val.length) {
        arr_val[2] = null;
        arr_val[3] = null;
    }

    return arr_val;
}


// **************************************** 框选联动注册 **************************************** //
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    初始化注册弹窗联动函数；
 * 参数:
 *    NA
 * 返回:
 *    @returns { Promise<Object> } 实例对象
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2020-12-28
 *       内容 : 所有代码
 *    2. 类型 : 添加
 *       作者 : 陈小荟
 *       时间 : 2020-01-09
 *       内容 : 添加大屏弹层根据侧边修改大屏name 更新显示name
 ************************************************************************************************/
function init_page_popup_link() {
    var obj = new construct_page_popup_link_data();

    // 连线弹窗
    var obj_page_arrange = obj.new_page_key("arrange_mod.html");

    obj_page_arrange.set_opt("type", "connect");
    obj_page_arrange.set_type(["select"]);
    obj_page_arrange.set_fun(mc_selectd_link_data_port);

    // obj_page_arrange.set_opt("type", "position");
    // obj_page_arrange.set_type(["select"]);
    // obj_page_arrange.set_fun(mc_select_check_module_item);

    // 合并弹窗
    var obj_page_merge = obj.new_page_key("merge_mod.html");

    obj_page_merge.set_type(["select", "move"]);
    obj_page_merge.set_fun(mc_selectd_link_data_merge);

    // 添加模块弹窗
    var obj_page_add = obj.new_page_key("check_mod.html");

    obj_page_add.set_opt("add_choose", "mod");
    obj_page_add.set_type(["modify"]);
    obj_page_add.set_fun(parent.mc_update_add_page_popup_show_name);

    obj_page_add.set_opt("add_choose", "box");
    obj_page_add.set_type(["modify"]);
    obj_page_add.set_fun(parent.mc_update_add_page_popup_show_name);

    obj_page_add.set_opt("add_choose", "screen");
    obj_page_add.set_type(["modify"]);
    obj_page_add.set_fun(parent.mc_update_add_page_popup_show_name);

    return obj;
}

/********************************************组合相关*********************************************/
/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    1. 判断是否可进行组合
 *    2. 若可进行组合 获取组合模块数据
 * 参数:
 *    @param { Promise<Array> } arr_select_list 选中模块数组
 *    @param { Promise<Object> } obj_same_hub_queue 连线队列
 * 返回：
 *    @return { Promise<Object> }
 *    null 参数/数据有误
 *    {
 *      str_key: str_key,
 *      obj_module_data: o_data,
 *      arr_boundary_potsize: [
 *          ui_min_x / ui_grid_w,
 *          ui_min_y / ui_grid_w,
 *          (ui_max_x - ui_min_x) / ui_grid_w,
 *          ( ui_max_y - ui_min_y) / ui_grid_w
 *      ]
 *    };
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.04.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_handle_compose_msg(arr_select_list, obj_same_hub_queue) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_select_list) || "[object Object]" !== Object.prototype.toString.call(obj_same_hub_queue)) {
        return null;
    }
    if (0 === arr_select_list.length) {
        return null;
    }
    var obj_first_data = mc_get_module_str_data(arr_select_list[0]);

    if (!obj_first_data) {
        return null;
    }
    var obj_data = obj_first_data.obj_params;
    var str_key = obj_data.card_idx;

    // SENDPORT下卡不进行组合
    if (-1 === str_key.indexOf("_")) {
        return null;
    }
    str_key += ":" + obj_data.val;
    var arr_line_data = obj_same_hub_queue[str_key];

    // 未连线数据 || 同PORT下卡未全选中/多选情况
    if (!arr_line_data || arr_line_data.length !== arr_select_list.length) {
        return null;
    }
    // 选中模块字串信息对象
    var o_data = {};
    // 组合模块边界位置
    var ui_min_x = Math.pow(2, 32);
    var ui_min_y = Math.pow(2, 32);
    var ui_max_x = 0;
    var ui_max_y = 0;
    var ui_grid_w = Number(document.getElementById("mod_box_next").getAttribute("grid_w"));

    o_data[obj_first_data.str_id] = obj_data;

    for (var index = 0; index < arr_select_list.length; index++) {
        if (0 !== index) {
            var o_target_data = mc_get_module_str_data(arr_select_list[index]);
            var obj_target_data = o_target_data.obj_params;
            var str_target_key = obj_target_data.card_idx + ":" + obj_target_data.val;

            // 存在其余队列卡
            if (str_target_key !== str_key) {
                return null;
            }
            // 存在新建卡
            if ("ALL" === o_target_data.ctrlchip_name) {
                return null;
            }
            o_data[o_target_data.str_id] = obj_target_data;
        }
        // 获取整体偏移大小信息
        var obj_target_js = arr_select_list[index][0];
        var arr_pot = mc_get_optsize_msg(obj_target_js, false, true);
        var arr_size = mc_get_optsize_msg(obj_target_js, true);
        // 偏移减去外接据项偏差
        var u_min_x = arr_pot[0];
        var u_min_y = arr_pot[1];
        var u_max_x = u_min_x + arr_size[0];
        var u_max_y = u_min_y + arr_size[1];

        if (ui_min_x > u_min_x) {
            ui_min_x = u_min_x;
        }
        if (ui_min_y > u_min_y) {
            ui_min_y = u_min_y;
        }
        if (ui_max_x < u_max_x) {
            ui_max_x = u_max_x;
        }
        if (ui_max_y < u_max_y) {
            ui_max_y = u_max_y;
        }
    }
    return {
        str_key: str_key,
        obj_module_data: o_data,
        arr_boundary_potsize: [
            ui_min_x / ui_grid_w,
            ui_min_y / ui_grid_w,
            (ui_max_x - ui_min_x) / ui_grid_w,
            (ui_max_y - ui_min_y) / ui_grid_w
        ]
    };
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取模块创建字串信息对象
 * 参数:
 *    @param { Promise<Object> } obj_jq jq对象
 *    @param { Promise<Number> } ui_idx 在连线队列中位置 可为空
 * 返回：
 *    @return { Promise<Object> }
 *    null 参数/数据有误
 *    { str_id: "id", obj_params: {创建字串信息对象} }
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.04.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_module_str_data(obj_jq, ui_idx) {
    if ("[object Object]" !== Object.prototype.toString.call(obj_jq)) {
        return null;
    }
    var obj_js = obj_jq[0];
    var obj_msg_box = obj_jq.children(".mod_msg_box");
    var arr_transform = mc_analysis_transform_msg(obj_js, "all");
    var obj_msg = mc_get_child_pot_size(obj_js);
    var arr_pot = obj_msg.str_pot.split(",");
    var arr_size = obj_msg.str_size.split("X");
    var str_idx = "[object Number]" === Object.prototype.toString.call(ui_idx) ? String(ui_idx) : obj_msg_box.children(".mod_list_idx").text();
    var ui_grid_w = Number(document.getElementById("mod_box_next").getAttribute("grid_w"));
    var boundary_size = [];

    if (arr_transform) {
        boundary_size = [Number(arr_transform[0][0]) / ui_grid_w, arr_transform[0][1] / ui_grid_w];
        arr_transform = [arr_transform[2][0], arr_transform[2][1], arr_transform[1], arr_transform[3]];
    } else {
        arr_transform = [];
        boundary_size = arr_size;
    }
    var obj_params = new format_mod_data();

    obj_params.width = arr_size[0];
    obj_params.height = arr_size[1];
    obj_params.left = arr_pot[0];
    obj_params.top = arr_pot[1];
    obj_params.val = obj_jq.children(".mod_hub_box").children(".mod_hub_div").text();
    obj_params.name = obj_jq.attr("mod_id");
    obj_params.ctrlchip_name = obj_msg_box.children(".chip_name").text();
    obj_params.transform_param = arr_transform;
    obj_params.card_idx = obj_jq.children(".mc_mod_right_bto").children(".card_idx").text();
    obj_params.list_idx = str_idx;
    obj_params.show_name = obj_msg_box.children(".mod_show_name").text();
    // 模块大小 ，若变换为外接矩形大小
    obj_params.boundary_size = boundary_size;
    // 初始模块大小
    obj_params.arr_initial_size = [obj_js.getAttribute("mod_wg"), obj_js.getAttribute("mod_hg")];

    return {
        str_id: obj_jq.attr("id"),
        obj_params: obj_params
    };
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    过滤组合块（编辑小块） [组合元素 不允许进行变换、替换]
 * 参数:
 *    @param { Promise<Array> } arr_select_list 选中队列
 *    @param { Promise<Boolean> } b_flier 是否过滤编辑小块 可为空 默认不过滤
 * 返回：
 *    @return { Promise<Array> }
 *    [] 参数/数据有误
 *    arr_select_list 过滤后数组
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.04.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_filter_compose_module(arr_select_list, b_flier) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_select_list)) {
        return [];
    }
    for (var i = 0; i < arr_select_list.length; i++) {
        var element = arr_select_list[i];

        if (mc_judge_is_compose_module(element) || (b_flier && element.hasClass("compose_edit"))) {
            arr_select_list.splice(i, 1);
        }
    }
    return arr_select_list;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    判断元素是否为组合元素
 * 参数:
 *    @param { Promise<Object> } obj_jq jq对象
 * 返回：
 *    @return { Promise<Boolean> }
 *    true 是
 *    false否
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.04.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_judge_is_compose_module(obj_jq) {
    if ("[object Object]" === Object.prototype.toString.call(obj_jq) && obj_jq.hasClass("mc_compose_mod")) {
        return true;
    }
    return false;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    判断此接口是否可设置组合卡（已设置过组合卡不允许设置）
 * 参数:
 *    @param { Promise<String> } str_set_key 选中队列
 *    @param { Promise<Array> } arr_compose_key 已存在组合卡key
 * 返回：
 *    @return { Promise<Array> }
 *    [] 参数/数据有误
 *    arr_select_list 过滤后数组
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.04.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_judge_b_setcard(str_set_key, arr_compose_key) {
    if ("[object String]" !== Object.prototype.toString.call(str_set_key)) {
        return false;
    }
    if ("[object Array]" !== Object.prototype.toString.call(arr_compose_key)) {
        return false;
    }
    for (var i = 0; i < arr_compose_key.length; i++) {
        if (arr_compose_key[i] === str_set_key) {
            return false;
        }
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取编辑外框HTML字串
 * 参数:
 *    @param { Promise<Array> } arr_pot_size [left,top,width,height]
 * 返回：
 *    @return { Promise<String> }
 *    "" 参数/数据有误
 *    HTML字串
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.04.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_edit_border_html(arr_pot_size) {
    if ("[object Array]" !== Object.prototype.toString.call(arr_pot_size)) {
        return "";
    }
    if (0 === arr_pot_size.length) {
        return "";
    }
    var ui_grid = Number(document.getElementById("mod_box_next").getAttribute("grid_w"));
    var str_style = "left:" + Number(arr_pot_size[0]) * ui_grid + "px;top:" + Number(arr_pot_size[1]) * ui_grid + "px;width:" + Number(arr_pot_size[2]) * ui_grid + "px;height:" + Number(arr_pot_size[3]) * ui_grid + "px;";

    return "<div id='mc_edit_border' style='" + str_style + "' ></div>";
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    切换编辑状态-隐藏显示除拆分块外其余块 及连线层 禁用遮罩
 * 参数:
 *    @param { Promise<Object> } obj_edit_btn 菜单栏编辑按钮
 *    @param { Promise<Boolean> } b_display 是否开启编辑
 * 返回：
 *    @return { Promise<Boolean> }
 *    false 参数/数据有误
 *    true 设置成功
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.04.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_edit_display(obj_edit_btn, b_display) {
    if ("[object HTMLDivElement]" !== Object.prototype.toString.call(obj_edit_btn)) {
        return false;
    }
    if (b_display) {
        obj_edit_btn.classList.add("mc_progress_edit");
        $(".mc_mod").not(".compose_edit").css("display", "none");
        $("#mc_hl_svg_layer_line").css("display", "none");
        $("#mc_hlever_layout_edit_gp").addClass("disable_mask");
        $(".mc_btn_group").addClass("disable_mask");
    } else {
        obj_edit_btn.classList.remove("mc_progress_edit");
        $(".mc_mod").not(".compose_edit").css("display", "block");
        $("#mc_hl_svg_layer_line").css("display", "block");
        $("#mc_hlever_layout_edit_gp").removeClass("disable_mask");
        $(".mc_btn_group").removeClass("disable_mask");
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取编辑虚线框偏移大小信息
 * 参数:
 *    NA
 * 返回：
 *    @return { Promise<Object> }
 *    {} 参数/数据有误
 *    {arr_pot:[X,Y], arr_size:[W,H]} 均为格子数
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.04.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_edit_border_msg() {
    var obj_edit = document.getElementById("mc_edit_border");
    var ui_grid = Number(document.getElementById("mod_box_next").getAttribute("grid_w"));

    if (!obj_edit) {
        return {};
    }
    return {
        arr_pot: [Math.round(obj_edit.offsetLeft / ui_grid), Math.round(obj_edit.offsetTop / ui_grid)],
        arr_size: [Math.round(obj_edit.offsetWidth / ui_grid), Math.round(obj_edit.offsetHeight / ui_grid)]
    };
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    记录编辑操作
 * 参数:
 *    无
 * 返回：
 *    NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.04.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_save_compose_edit_operate() {
    this.operate_param = new mc_layout_operate_format_data();

    // 设置操作参数
    this.get_param = function () {
        return this.operate_param;
    };

    // 重置操作参数
    this.clear_param = function () {
        this.operate_param = new mc_layout_operate_format_data();
        return true;
    };

    // 存储本次操作
    this.save_operate = function (str_type) {
        if ("[object String]" !== Object.prototype.toString.call(str_type)) {
            return false;
        }
        mc_layout_operate(str_type, this.operate_param);
        return true;
    };
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    判断是否为组合块 返回小块信息（更新后的数据）
 * 参数:
 *    @param { Promise<Object> } obj_jq jq元素
 * 返回：
 *    @return { Promise<Object> }
 *    null 参数/数据有误
 *    obj_module_data 构建模块字串信息对象
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.04.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_judge_get_compose_data(obj_jq) {
    if ("[object Object]" !== Object.prototype.toString.call(obj_jq)) {
        return null;
    }
    if (mc_judge_is_compose_module(obj_jq)) {
        var str_key = obj_jq.attr("compose_key");
        var obj_compose_data = obj_compose.updata_compose_blk_msg(str_key);

        if (!obj_compose_data) {
            return {};
        }
        return obj_compose_data.obj_module_data;
    }
    return null;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    发送/固化偏移 获取数据（处理组合模块情况）
 * 参数:
 *    @param { Promise<Object> } obj_jq jq元素
 *    @param { Promise<String> } str_chip_name 芯片信息
 * 返回：
 *    @return { Promise<Boolean> }
 *    [] 参数/数据有误
 *    arr_recv 处理后数据
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.04.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_sendoffset_handle_compose_data(obj_jq, str_chip_name) {
    var arr_recv = [];
    var obj_module_data = mc_judge_get_compose_data(obj_jq);

    if (obj_module_data) {
        var arr_key = Object.keys(obj_module_data);

        for (var idx = 0; idx < arr_key.length; idx++) {
            var element = arr_key[idx];

            var obj_item_data = obj_module_data[element];

            arr_recv[Number(obj_item_data.list_idx) - 1] = {
                X: Number(obj_item_data.left),
                Y: Number(obj_item_data.top),
                W: Number(obj_item_data.boundary_size[0]),
                H: Number(obj_item_data.boundary_size[1]),
                CHIP_NAME: str_chip_name || obj_jq.children(".mod_msg_box").children(".chip_name").text()
            };
        }
    } else {
        var obj_js = obj_jq[0];
        var obj_msg = mc_get_child_pot_size(obj_js);
        var arr_pot = obj_msg.str_pot.split(",");

        // 变换元素获取外接矩形宽高
        var arr_size = mc_analysis_transform_msg(obj_js);

        if (!arr_size) {
            arr_size = obj_msg.str_size.split("X");
        } else {
            var ui_grid_w = Number(document.getElementById("mod_box_next").getAttribute("grid_w"));

            arr_size[0] /= ui_grid_w;
            arr_size[1] /= ui_grid_w;
        }

        arr_recv.push({
            X: Number(arr_pot[0]),
            Y: Number(arr_pot[1]),
            W: Number(arr_size[0]),
            H: Number(arr_size[1]),
            CHIP_NAME: str_chip_name || obj_jq.children(".mod_msg_box").children(".chip_name").text()
        });
    }
    return arr_recv;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    发送/固化偏移箱体 获取数据（处理组合模块情况）
 * 参数:
 *    @param { Promise<Object> } obj_js js元素
 *    @param { Promise<Object> } obj_box_size 箱体宽高
 *    @param { Promise<Array> } ary_box_data ARY_BOX_DATA
 *    @param { Promise<Array> } ary_mod_data ARY_MOD_DATA
 *    @param { Promise<Object> } obj_integration_data
 *    @param { Promise<String> } str_param
 *    @param { Promise<Number> } i_recv
 * 返回：
 *    @return { Promise<Object> }
 *    [] 参数/数据有误
 *    obj_integration_data
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.04.16
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_sendbox_handle_compose_data(obj_js, obj_box_size, ary_box_data,
    ary_mod_data, obj_integration_data, str_param, i_recv) {
    if ("[object HTMLDivElement]" !== Object.prototype.toString.call(obj_js)) {
        return "";
    }
    // 获取组合模块 子模块数据
    var obj_module_data = mc_judge_get_compose_data($(obj_js));
    var str_key = "";

    if (obj_module_data) {
        var arr_key = Object.keys(obj_module_data);

        for (var idx = 0; idx < arr_key.length; idx++) {
            var element = arr_key[idx];

            var obj_item_data = obj_module_data[element];
            var obj_data = new format_transform_data();

            var str_box_name = obj_item_data.name;
            var str_page_size = obj_item_data.arr_initial_size[0] + ":" + obj_item_data.arr_initial_size[1] + ")";
            var str_size = "65535:65535)";
            var arr_transform_param = obj_item_data.transform_param;

            // 图像大小与变换无关 且 若设置过图像大小 WH数据为设置数据 否则置为655*355
            // 无箱体大小数据 添加
            if (!obj_box_size[str_box_name]) {
                var arr_box_size = mc_layout_get_box_size(str_box_name, ary_box_data, ary_mod_data);

                if (arr_box_size) {
                    obj_box_size[str_box_name] = "(" + arr_box_size[0] + ":" + arr_box_size[1] + ")";
                }
            }
            // 对比 若更改使用更改数据
            if (obj_box_size[str_box_name] !== "(" + str_page_size) {
                str_size = str_page_size;
            }
            obj_data.str_size = str_size;
            obj_data.str_box_name = str_box_name;
            obj_data.str_chip_name = obj_item_data.ctrlchip_name;

            if (0 !== arr_transform_param.length) {
                var ui_angle = Number(arr_transform_param[2]);

                // angle = 360置为0
                if (ui_angle && 360 !== ui_angle) {
                    obj_data.str_rotation = "(0:0:" + ui_angle + ")";
                }
                obj_data.str_scale = "(0:0:" + arr_transform_param[0] + ":" + arr_transform_param[1] + ")";
                obj_data.str_mirror = String(arr_transform_param[3]);
                obj_data.str_cut = arr_transform_param[4];
                var arr_cut = arr_transform_param[4].split(",");

                obj_data.str_size = "(" + arr_cut[0] + ":" + arr_cut[2] + obj_data.str_size;
            } else {
                obj_data.str_size = "(0:0:" + obj_data.str_size;
            }
            var str_data_key = obj_data.str_box_name + "_" + obj_data.str_chip_name + "_" + obj_data.str_rotation + "_" + obj_data.str_scale + "_" + obj_data.str_mirror + "_" + str_size;

            str_key = str_data_key + "_" + str_param;
            obj_integration_data = add_data(obj_integration_data, str_key, {
                "idx": "(" + str_param + ":" + (Number(obj_item_data.list_idx) - 1) + ")",
                "data": obj_data
            });
        }
    } else {
        var arr_data = mc_get_transform_data(obj_js, obj_box_size, ary_box_data, ary_mod_data);

        str_key = arr_data[1] + "_" + str_param;
        obj_integration_data = add_data(obj_integration_data, str_key, {
            "idx": "(" + str_param + ":" + i_recv + ")",
            "data": arr_data[0]
        });
    }

    return str_key;

    // 添加对象数据 对象，key，data
    function add_data(o_data, str_keys, o_item_data) {
        if (o_data[str_keys]) {
            o_data[str_keys].idx += "," + o_item_data.idx;
        } else {
            o_data[str_keys] = o_item_data;
        }
        return o_data;
    }
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    保存当前画布连线块为点位图
 * 参数:
 *    无
 * 返回：
 *    NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 陈小荟
 *      时间 : 2021.12.22
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_save_bitmap() {
    var arr_key = Object.keys(obj_same_hub_queue);

    if (arr_key.length) {
        var ui_grid_w = Number(document.getElementById("mod_box_next").getAttribute("grid_w"));

        var arr_dot = [];
        var ui_min_x = Math.pow(2, 32);
        var ui_min_y = Math.pow(2, 32);
        var ui_max_x = 0;
        var ui_max_y = 0;

        for (var index = 0; index < arr_key.length; index++) {
            var arr_line_data = obj_same_hub_queue[arr_key[index]];

            if (!arr_line_data.length) {
                continue;
            }
            for (var idx = 0; idx < arr_line_data.length; idx++) {
                var obj_item = arr_line_data[idx][0];
                var obj_data = new format_data();
                var obj_msg = mc_get_child_pot_size(obj_item);
                var arr_pot = obj_msg.str_pot.split(",");
                var arr_size = obj_msg.str_size.split("X");
                var arr_transform_msg = mc_analysis_transform_msg(obj_item, "all");
                var ui_area_w = 0;
                var ui_area_h = 0;

                obj_data.w = Number(arr_size[0]);
                obj_data.h = Number(arr_size[1]);
                if (arr_transform_msg) {
                    ui_area_w = Number(arr_transform_msg[0][0]) / ui_grid_w;
                    ui_area_h = Number(arr_transform_msg[0][1]) / ui_grid_w;
                    obj_data.rotate = Number(arr_transform_msg[1]);
                    obj_data.scalex = Number(arr_transform_msg[2][0]);
                    obj_data.scaley = Number(arr_transform_msg[2][1]);
                    obj_data.mirror = Number(arr_transform_msg[3]);

                    obj_data.x = (ui_area_w - obj_data.w) / 2;
                    obj_data.y = (ui_area_h - obj_data.h) / 2;
                } else {
                    ui_area_w = Number(arr_size[0]);
                    ui_area_h = Number(arr_size[1]);
                }

                obj_data.x += Number(arr_pot[0]);
                obj_data.y += Number(arr_pot[1]);
                arr_dot.push(obj_data);

                if (ui_min_x > Number(arr_pot[0])) {
                    ui_min_x = Number(arr_pot[0]);
                }
                if (ui_min_y > Number(arr_pot[1])) {
                    ui_min_y = Number(arr_pot[1]);
                }
                if (ui_max_x < Number(arr_pot[0]) + ui_area_w) {
                    ui_max_x = Number(arr_pot[0]) + ui_area_w;
                }
                if (ui_max_y < Number(arr_pot[1]) + ui_area_h) {
                    ui_max_y = Number(arr_pot[1]) + ui_area_h;
                }
            }
        }
        if (arr_dot.length) {
            mc_bitmap(arr_dot, ui_max_x - ui_min_x, ui_max_y - ui_min_y, ui_min_x, ui_min_y);
        }
    }
    return;
    function format_data() {
        this.x = 0;
        this.y = 0;
        this.w = 0;
        this.h = 0;
        this.rotate = 0;
        this.scalex = 1;
        this.scaley = 1;
        this.mirror = 0;
    }
}


/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    下发hub预设值;
 * 参数:
 *    @param { Promise<String> } obj_queue 连线队列
 *    @param { Promise<Function> } callback 回调(true)
 * 返回:
 *    @returns { Promise<Boolean> } 参数1
 * 例子:
 *    NA
 * 备注:
 *    NA
 * 修改:
 *    1. 类型 : 创建
 *       作者 : 巫昭雯
 *       时间 : 2021-12-23
 *       内容 : 所有代码
************************************************************************************************/
function mc_hl_send_hub_preset(obj_queue, callback) {
    callback = "function" === typeof callback ? callback : function () {
        return 0;
    };
    if (!mc_util_is_object(obj_queue)) {
        return callback(false);
    }

    // obj_data = {发送卡:{输出口:分控cnt, 最大分控:0}}
    var obj_data = {};
    var obj_temp = {};
    var str_temp = "";
    var arr_key = [];
    var ui_h = 0, ui_p = 0, ui_s = 0;

    for (var key in obj_queue) {
        if (Object.hasOwnProperty.call(obj_queue, key)) {
            if (!key || -1 === key.toLocaleUpperCase().indexOf("H")) {
                continue;
            }
            if ("object" === typeof obj_queue[key] && obj_queue[key].length && (arr_key = mc_get_line_key_val(key, true))) {
                // save line key
                ui_s = Number(arr_key[0]) - 1;
                ui_p = Number(arr_key[1]) - 1;
                ui_h = Number(arr_key[2]) - 1;
                str_temp = ui_s + "_" + ui_p + "_" + ui_h;
                if (obj_temp[str_temp]) {
                    continue;
                }
                obj_temp[str_temp] = true;
                // save port hub cont
                if (!obj_data[ui_s]) {
                    obj_data[ui_s] = {
                        max_p: 0
                    };
                }
                if ("number" !== typeof obj_data[ui_s][ui_p]) {
                    obj_data[ui_s][ui_p] = ui_h;
                }
                if (ui_h > obj_data[ui_s][ui_p]) {
                    obj_data[ui_s][ui_p] = ui_h;
                }
                // save max port
                if (ui_p > obj_data[ui_s].max_p) {
                    obj_data[ui_s].max_p = ui_p;
                }
            }
        }
    }

    // set param
    var obj_sdk_param = new mc_sdk_param();

    for (var key_s in obj_data) {
        if (Object.hasOwnProperty.call(obj_data, key_s)) {
            var obj_p = obj_data[key_s];
            var ui_p_i = 0;
            var str_req = "";

            while (ui_p_i <= obj_p.max_p) {
                if ("number" === typeof obj_p[ui_p_i]) {
                    str_req += (obj_p[ui_p_i] + 1) + ",";
                } else {
                    str_req += "0,";
                }
                ui_p_i++;
            }
            obj_sdk_param.set_param_value(key_s + "", str_req.substring(0, str_req.length - 1));
        }
    }

    // send
    mc_io_hw_hub_preset_status(obj_sdk_param.get_json(), function (str_json) {  /* eslint-disable-line */
        return callback(true);
    }, 1);
    return true;
}
